1. Giới thiệu
Thành phần Material (MDC) giúp nhà phát triển triển khai Material Design. Được tạo bởi một nhóm các kỹ sư và nhà thiết kế trải nghiệm người dùng tại Google, MDC có hàng chục thành phần giao diện người dùng đẹp mắt, dễ sử dụng và được cung cấp cho Android, iOS, web và Flutter.material.io/develop |
Trong lớp học lập trình MDC-101, bạn đã sử dụng 2 Thành phần Material (MDC) để xây dựng trang đăng nhập: các trường văn bản và nút có gợn sóng của mực. Bây giờ, hãy mở rộng nền tảng này bằng cách thêm thành phần điều hướng, cấu trúc và dữ liệu.
Sản phẩm bạn sẽ tạo ra
Trong lớp học lập trình này, bạn sẽ xây dựng màn hình chính cho một ứng dụng có tên là Shrine (Đền thờ). Đây là một ứng dụng thương mại điện tử bán quần áo và đồ gia dụng. Bản tóm tắt sẽ chứa:
- Thanh ứng dụng trên cùng
- Một danh sách lưới gồm nhiều sản phẩm
Các thành phần MDC-Android trong lớp học lập trình này
- AppBarLayout
- MaterialCardView
Bạn cần có
- Kiến thức cơ bản về phát triển Android
- Android Studio (tải xuống tại đây nếu bạn chưa có)
- Trình mô phỏng hoặc thiết bị Android (có trên Android Studio)
- Mã mẫu (xem bước tiếp theo)
Bạn đánh giá mức độ kinh nghiệm xây dựng ứng dụng Android của mình ở mức nào?
2. Thiết lập môi trường phát triển
Bạn đang tiếp tục từ khoá học MDC-101?
Nếu bạn đã hoàn thành MDC-101, thì bạn đã chuẩn bị sẵn mã cho lớp học lập trình này. Chuyển sang bước 3: Thêm thanh ứng dụng trên cùng.
Bạn muốn bắt đầu từ đầu?
Tải ứng dụng ban đầu của lớp học lập trình xuống
Ứng dụng khởi động nằm trong thư mục material-components-android-codelabs-102-starter/kotlin
. Hãy nhớ cd
vào thư mục đó trước khi bắt đầu.
...hoặc sao chép tệp trên GitHub
Để sao chép lớp học lập trình này từ GitHub, hãy chạy các lệnh sau:
git clone https://github.com/material-components/material-components-android-codelabs cd material-components-android-codelabs/ git checkout 102-starter
Tải mã khởi đầu trong Android Studio
- Sau khi trình hướng dẫn thiết lập hoàn tất và cửa sổ Welcome to Android Studio (Chào mừng bạn đến với Android Studio) hiển thị, hãy nhấp vào Open an existing Android Studio project (Mở một dự án Android Studio hiện có). Chuyển đến thư mục mà bạn đã cài đặt mã mẫu rồi chọn kotlin -> shrine (hoặc tìm shrine trên máy tính) để mở dự án Shipping.
- Chờ một lát để Android Studio tạo và đồng bộ hoá dự án, như được hiển thị bằng các chỉ báo hoạt động ở cuối cửa sổ Android Studio.
- Tại thời điểm này, Android Studio có thể phát sinh một số lỗi bản dựng do bạn đang thiếu SDK Android hoặc công cụ xây dựng, chẳng hạn như lỗi hiển thị dưới đây. Làm theo hướng dẫn trong Android Studio để cài đặt/cập nhật các ứng dụng này và đồng bộ hoá dự án của bạn.
Thêm phần phụ thuộc của dự án
Dự án cần có phần phụ thuộc trên thư viện hỗ trợ MDC Android. Mã mẫu bạn tải xuống đã liệt kê phần phụ thuộc này, nhưng bạn nên thực hiện các bước sau đây để đảm bảo phần phụ thuộc này.
- Chuyển đến tệp
build.gradle
của mô-đunapp
và đảm bảo rằng khốidependencies
bao gồm một phần phụ thuộc trên MDC Android:
api 'com.google.android.material:material:1.1.0-alpha06'
- (Không bắt buộc) Nếu cần, hãy chỉnh sửa tệp
build.gradle
để thêm các phần phụ thuộc sau và đồng bộ hoá dự án.
dependencies { api 'com.google.android.material:material:1.1.0-alpha06' implementation 'androidx.legacy:legacy-support-v4:1.0.0' implementation 'com.android.volley:volley:1.1.1' implementation 'com.google.code.gson:gson:2.8.5' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.21" testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test:core:1.1.0' androidTestImplementation 'androidx.test.ext:junit:1.1.0' androidTestImplementation 'androidx.test:runner:1.2.0-alpha05' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0-alpha05' }
Chạy ứng dụng ban đầu
|
Thành công! Bạn sẽ thấy trang đăng nhập Shrine từ lớp học lập trình MDC-101.
Giờ đây, màn hình đăng nhập đã trông ổn, hãy điền một số sản phẩm vào ứng dụng.
3. Thêm thanh ứng dụng trên cùng
Màn hình chính sẽ xuất hiện khi trang đăng nhập đóng lại, với màn hình cho biết "Bạn đã làm được!". Thật tuyệt! Nhưng giờ đây, người dùng không cần làm gì hoặc không biết họ đang ở đâu trong ứng dụng. Để làm được điều đó, hãy thêm tính năng điều hướng.
Material Design cung cấp các mẫu điều hướng đảm bảo mức độ hữu dụng cao. Một trong những thành phần dễ thấy nhất là thanh ứng dụng trên cùng.
Để cung cấp tính năng điều hướng và cho phép người dùng truy cập nhanh vào các thao tác khác, hãy thêm một thanh ứng dụng ở trên cùng.
Thêm tiện ích AppBar
Trong shr_product_grid_fragment.xml
, hãy xoá khối <LinearLayout>
chứa dòng chữ "Bạn đã làm được!" TextView
và thay thế bằng nội dung sau:
shr_product_grid_fragment.xml
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.Toolbar
android:id="@+id/app_bar"
style="@style/Widget.Shrine.Toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:title="@string/shr_app_name" />
</com.google.android.material.appbar.AppBarLayout>
Bây giờ, shr_product_grid_fragment.xml
của bạn sẽ có dạng như sau:
shr_product_grid_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ProductGridFragment">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.Toolbar
android:id="@+id/app_bar"
style="@style/Widget.Shrine.Toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:title="@string/shr_app_name" />
</com.google.android.material.appbar.AppBarLayout>
</FrameLayout>
Nhiều thanh ứng dụng có một nút bên cạnh tiêu đề. Hãy thêm biểu tượng trình đơn vào ứng dụng của chúng ta.
Thêm biểu tượng điều hướng
Khi vẫn ở trong shr_product_grid_fragment.xml
, hãy thêm đoạn mã sau vào thành phần XML Toolbar
mà bạn vừa thêm vào bố cục:
shr_product_grid_fragment.xml
app:navigationIcon="@drawable/shr_menu"
shr_product_grid_fragment.xml
của bạn sẽ có dạng như sau:
shr_product_grid_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ProductGridFragment">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.Toolbar
android:id="@+id/app_bar"
style="@style/Widget.Shrine.Toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:navigationIcon="@drawable/shr_menu"
app:title="@string/shr_app_name" />
</com.google.android.material.appbar.AppBarLayout>
</FrameLayout>
Thêm các nút hành động và tạo kiểu cho thanh ứng dụng trên cùng
Bạn cũng có thể thêm các nút vào phía cuối của thanh ứng dụng. Trong Android, các nút này được gọi là nút hành động. Chúng ta sẽ tạo kiểu cho thanh ứng dụng trên cùng và thêm các nút hành động vào trình đơn theo phương thức lập trình.
Trong hàm onCreateView
của ProductGridFragment.kt
, hãy đặt Toolbar
của activity
để được dùng làm ActionBar
bằng setSupportActionBar
. Bạn có thể thực hiện việc này sau khi tạo thành phần hiển thị bằng inflater
.
ProductGridFragment.kt
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment with the ProductGrid theme
val view = inflater.inflate(R.layout.shr_product_grid_fragment, container, false)
// Set up the toolbar.
(activity as AppCompatActivity).setSupportActionBar(view.app_bar)
return view;
}
Tiếp theo, ngay bên dưới phương thức mà chúng ta vừa thay đổi để thiết lập thanh công cụ, hãy ghi đè onCreateOptionsMenu
để tăng cường nội dung của shr_toolbar_menu.xml
vào thanh công cụ:
ProductGridFragment.kt
override fun onCreateOptionsMenu(menu: Menu, menuInflater: MenuInflater) {
menuInflater.inflate(R.menu.shr_toolbar_menu, menu)
super.onCreateOptionsMenu(menu, menuInflater)
}
Cuối cùng, ghi đè onCreate()
trong ProductGridFragment.kt
và sau khi gọi super()
, hãy gọi setHasOptionMenu
bằng true
:
ProductGridFragment.kt
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
}
Các đoạn mã ở trên đặt thanh ứng dụng trong bố cục XML của chúng ta thành Thanh thao tác cho hoạt động này. Lệnh gọi lại onCreateOptionsMenu
cho hoạt động biết nội dung cần sử dụng làm trình đơn. Trong trường hợp này, trình đơn này sẽ đặt các mục trong trình đơn từ R.menu.shr_toolbar_menu
vào thanh ứng dụng. Tệp trình đơn chứa hai mục: "Tìm kiếm" và "Bộ lọc".
shr_toolbar_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/search"
android:icon="@drawable/shr_search"
android:title="@string/shr_search_title"
app:showAsAction="always" />
<item
android:id="@+id/filter"
android:icon="@drawable/shr_filter"
android:title="@string/shr_filter_title"
app:showAsAction="always" />
</menu>
Sau những thay đổi đó, tệp ProductGridFragment.kt
của bạn sẽ có dạng như sau:
ProductGridFragment.kt
package com.google.codelabs.mdc.kotlin.shrine
import android.os.Bundle
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.GridLayoutManager
import com.google.codelabs.mdc.kotlin.shrine.network.ProductEntry
import kotlinx.android.synthetic.main.shr_product_grid_fragment.view.*
class ProductGridFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment with the ProductGrid theme
val view = inflater.inflate(R.layout.shr_product_grid_fragment, container, false)
// Set up the tool bar
(activity as AppCompatActivity).setSupportActionBar(view.app_bar)
return view;
}
override fun onCreateOptionsMenu(menu: Menu, menuInflater: MenuInflater) {
menuInflater.inflate(R.menu.shr_toolbar_menu, menu)
super.onCreateOptionsMenu(menu, menuInflater)
}
}
Tạo bản dựng và chạy. Màn hình chính của bạn sẽ có dạng như sau:
Giờ đây, thanh công cụ đã có biểu tượng điều hướng, tiêu đề và hai biểu tượng hành động ở bên phải. Thanh công cụ cũng hiển thị độ cao bằng một bóng đổ tinh tế cho biết thanh công cụ nằm trên một lớp khác với nội dung.
4. Thêm thẻ
Giờ đây, ứng dụng của chúng ta đã có một số cấu trúc, hãy sắp xếp nội dung bằng cách đặt nội dung đó vào thẻ.
Thêm thẻ
Hãy bắt đầu bằng cách thêm một thẻ bên dưới thanh ứng dụng trên cùng. Thẻ phải có khu vực cho hình ảnh, tiêu đề và nhãn cho văn bản phụ. Thêm nội dung sau vào shr_product_grid_fragment.xml
bên dưới AppBarLayout
.
shr_product_grid_fragment.xml
<com.google.android.material.card.MaterialCardView
android:layout_width="160dp"
android:layout_height="180dp"
android:layout_marginBottom="16dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginTop="70dp"
app:cardBackgroundColor="?attr/colorPrimaryDark"
app:cardCornerRadius="4dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="#FFFFFF"
android:orientation="vertical"
android:padding="8dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="2dp"
android:text="@string/shr_product_title"
android:textAppearance="?attr/textAppearanceHeadline6" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="2dp"
android:text="@string/shr_product_description"
android:textAppearance="?attr/textAppearanceBody2" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
Tạo và chạy:
Trong bản xem trước này, bạn có thể thấy thẻ được lồng ghép từ cạnh trái, có các góc bo tròn và bóng đổ (biểu thị độ cao của thẻ). Toàn bộ phần tử được gọi là "vùng chứa". Ngoài vùng chứa, bạn có thể cài đặt tất cả các phần tử trong vùng chứa đó.
Bạn có thể thêm các phần tử sau vào vùng chứa: văn bản tiêu đề, hình thu nhỏ hoặc hình đại diện, văn bản tiêu đề phụ, đường phân chia, thậm chí cả nút và biểu tượng. Ví dụ: thẻ chúng ta vừa tạo chứa hai TextView
(một cho tiêu đề và một cho văn bản phụ) trong LinearLayout
, được căn chỉnh ở cuối thẻ.
Thẻ thường xuất hiện trong một bộ sưu tập cùng với các thẻ khác. Trong phần tiếp theo của lớp học lập trình này, chúng ta sẽ bố trí chúng dưới dạng một tập hợp trong lưới.
5. Tạo một lưới thẻ
Khi có nhiều thẻ trong một màn hình, các thẻ đó sẽ được nhóm lại với nhau thành một hoặc nhiều bộ sưu tập. Các thẻ trong lưới là đồng phẳng, nghĩa là các thẻ này có cùng cao độ nghỉ ngơi với nhau (trừ phi được chọn hoặc kéo, nhưng chúng ta sẽ không đề cập đến điều đó trong lớp học lập trình này).
Thiết lập lưới thẻ
Hãy xem tệp shr_product_card.xml
mà chúng tôi đã cung cấp cho bạn:
shr_product_card.xml
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardBackgroundColor="@android:color/white"
app:cardElevation="2dp"
app:cardPreventCornerOverlap="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.android.volley.toolbox.NetworkImageView
android:id="@+id/product_image"
android:layout_width="match_parent"
android:layout_height="@dimen/shr_product_card_image_height"
android:background="?attr/colorPrimaryDark"
android:scaleType="centerCrop" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:id="@+id/product_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/shr_product_title"
android:textAppearance="?attr/textAppearanceHeadline6" />
<TextView
android:id="@+id/product_price"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/shr_product_description"
android:textAppearance="?attr/textAppearanceBody2" />
</LinearLayout>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
Bố cục thẻ này chứa một thẻ có hình ảnh (trong trường hợp này là NetworkImageView
, cho phép chúng ta tải và hiển thị hình ảnh từ một URL) và hai TextViews
.
Tiếp theo, hãy xem ProductCardRecyclerViewAdapter
mà chúng tôi đã cung cấp cho bạn. Lớp này nằm trong cùng một gói với ProductGridFragment
.
ProductCardRecyclerViewAdapter.kt
package com.google.codelabs.mdc.kotlin.shrine
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.google.codelabs.mdc.kotlin.shrine.network.ProductEntry
/**
* Adapter used to show a simple grid of products.
*/
class ProductCardRecyclerViewAdapter(private val productList: List<ProductEntry>) : RecyclerView.Adapter<ProductCardViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProductCardViewHolder {
val layoutView = LayoutInflater.from(parent.context).inflate(R.layout.shr_product_card, parent, false)
return ProductCardViewHolder(layoutView)
}
override fun onBindViewHolder(holder: ProductCardViewHolder, position: Int) {
// TODO: Put ViewHolder binding code here in MDC-102
}
override fun getItemCount(): Int {
return productList.size
}
}
Lớp chuyển đổi ở trên quản lý nội dung của lưới. Để xác định việc mỗi thành phần hiển thị sẽ làm gì với nội dung nhất định, chúng ta sẽ sớm viết mã cho onBindViewHolder()
.
Trong cùng một gói, bạn cũng có thể xem ProductCardViewHolder
. Lớp này lưu trữ những chế độ xem ảnh hưởng đến bố cục thẻ để chúng ta có thể sửa đổi sau.
package com.google.codelabs.mdc.kotlin.shrine
import android.view.View
import androidx.recyclerview.widget.RecyclerView
class ProductCardViewHolder(itemView: View) //TODO: Find and store views from itemView
: RecyclerView.ViewHolder(itemView)
Để thiết lập lưới, trước tiên, chúng ta cần xoá phần giữ chỗ MaterialCardView
khỏi shr_product_grid_fragment.xml
. Tiếp theo, bạn nên thêm thành phần đại diện cho lưới thẻ của chúng ta. Trong trường hợp này, chúng ta sẽ sử dụng RecyclerView. Thêm thành phần RecyclerView vào shr_product_grid_fragment.xml
bên dưới thành phần XML AppBarLayout
:
shr_product_grid_fragment.xml
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="56dp"
android:background="@color/productGridBackgroundColor"
android:paddingStart="@dimen/shr_product_grid_spacing"
android:paddingEnd="@dimen/shr_product_grid_spacing"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.core.widget.NestedScrollView>
shr_product_grid_fragment.xml
của bạn sẽ có dạng như sau:
shr_product_grid_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ProductGridFragment">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.Toolbar
android:id="@+id/app_bar"
style="@style/Widget.Shrine.Toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:navigationIcon="@drawable/shr_menu"
app:title="@string/shr_app_name" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="56dp"
android:background="@color/productGridBackgroundColor"
android:paddingStart="@dimen/shr_product_grid_spacing"
android:paddingEnd="@dimen/shr_product_grid_spacing"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.core.widget.NestedScrollView>
</FrameLayout>
Cuối cùng, trong onCreateView()
, hãy thêm mã khởi chạy RecyclerView
vào ProductGridFragment.kt
sau khi bạn gọi setUpToolbar(view)
và trước câu lệnh return
:
ProductGridFragment.kt
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment with the ProductGrid theme
val view = inflater.inflate(R.layout.shr_product_grid_fragment, container, false)
// Set up the toolbar.
(activity as AppCompatActivity).setSupportActionBar(view.app_bar)
// Set up the RecyclerView
view.recycler_view.setHasFixedSize(true)
view.recycler_view.layoutManager = GridLayoutManager(context, 2, RecyclerView.VERTICAL, false)
val adapter = ProductCardRecyclerViewAdapter(
ProductEntry.initProductEntryList(resources))
view.recycler_view.adapter = adapter
val largePadding = resources.getDimensionPixelSize(R.dimen.shr_product_grid_spacing)
val smallPadding = resources.getDimensionPixelSize(R.dimen.shr_product_grid_spacing_small)
view.recycler_view.addItemDecoration(ProductGridItemDecoration(largePadding, smallPadding))
return view;
}
Đoạn mã ở trên chứa các bước khởi chạy cần thiết để thiết lập RecyclerView
. Điều này bao gồm việc thiết lập trình quản lý bố cục của RecyclerView
, cũng như khởi chạy và thiết lập trình chuyển đổi của RecyclerView
.
Bây giờ, tệp ProductGridFragment.kt
của bạn sẽ có dạng như sau:
ProductGridFragment .kt
package com.google.codelabs.mdc.kotlin.shrine
import android.os.Bundle
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.codelabs.mdc.kotlin.shrine.network.ProductEntry
import kotlinx.android.synthetic.main.shr_product_grid_fragment.view.*
class ProductGridFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment with the ProductGrid theme
val view = inflater.inflate(R.layout.shr_product_grid_fragment, container, false)
// Set up the toolbar.
(activity as AppCompatActivity).setSupportActionBar(view.app_bar)
// Set up the RecyclerView
view.recycler_view.setHasFixedSize(true)
view.recycler_view.layoutManager = GridLayoutManager(context, 2, RecyclerView.VERTICAL, false)
val adapter = ProductCardRecyclerViewAdapter(
ProductEntry.initProductEntryList(resources))
view.recycler_view.adapter = adapter
val largePadding = resources.getDimensionPixelSize(R.dimen.shr_product_grid_spacing)
val smallPadding = resources.getDimensionPixelSize(R.dimen.shr_product_grid_spacing_small)
view.recycler_view.addItemDecoration(ProductGridItemDecoration(largePadding, smallPadding))
return view;
}
override fun onCreateOptionsMenu(menu: Menu, menuInflater: MenuInflater) {
menuInflater.inflate(R.menu.shr_toolbar_menu, menu)
super.onCreateOptionsMenu(menu, menuInflater)
}
}
Tạo và chạy:
Các thẻ đã xuất hiện! Các sản phẩm này chưa hiển thị gì cả, vì vậy, hãy thêm một số dữ liệu sản phẩm.
Thêm hình ảnh và văn bản
Đối với mỗi thẻ, hãy thêm hình ảnh, tên sản phẩm và giá. Mô-đun trừu tượng ViewHolder
của chúng ta lưu giữ các thành phần hiển thị cho mỗi thẻ. Trong ViewHolder
, hãy thêm ba thành phần hiển thị như sau.
ProductCardViewHolder.kt
package com.google.codelabs.mdc.kotlin.shrine
import android.view.View
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.android.volley.toolbox.NetworkImageView
class ProductCardViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var productImage: NetworkImageView = itemView.findViewById(R.id.product_image)
var productTitle: TextView = itemView.findViewById(R.id.product_title)
var productPrice: TextView = itemView.findViewById(R.id.product_price)
}
Cập nhật phương thức onBindViewHolder()
trong ProductCardRecyclerViewAdapter
để đặt tiêu đề, giá và hình ảnh sản phẩm cho từng chế độ xem sản phẩm như minh hoạ dưới đây:
ProductCardRecyclerViewAdapter.kt
override fun onBindViewHolder(holder: ProductCardViewHolder, position: Int) {
if (position < productList.size) {
val product = productList[position]
holder.productTitle.text = product.title
holder.productPrice.text = product.price
ImageRequester.setImageFromUrl(holder.productImage, product.url)
}
}
Mã ở trên cho bộ chuyển đổi của RecyclerView
biết cần làm gì với từng thẻ bằng cách sử dụng ViewHolder
.
Ở đây, lớp này thiết lập dữ liệu văn bản trên mỗi TextView
của ViewHolder
và gọi ImageRequester
để lấy hình ảnh từ URL. ImageRequester
là một lớp chúng tôi cung cấp để thuận tiện cho bạn và sử dụng thư viện Volley
(Đó là một chủ đề không thuộc phạm vi của lớp học lập trình này, nhưng bạn có thể tự khám phá mã nguồn này).
Tạo và chạy:
Sản phẩm của chúng tôi đang xuất hiện trong ứng dụng!
6. Tóm tắt
Ứng dụng của chúng ta có một quy trình cơ bản đưa người dùng từ màn hình đăng nhập đến màn hình chính, nơi họ có thể xem các sản phẩm. Chỉ với vài dòng mã, chúng ta đã thêm một thanh ứng dụng trên cùng có tiêu đề và 3 nút, cùng một lưới thẻ để trình bày nội dung của ứng dụng. Màn hình chính của chúng tôi hiện đơn giản và hữu ích, với cấu trúc cơ bản và nội dung có thể hành động.
Các bước tiếp theo
Với thanh ứng dụng, thẻ, trường văn bản và nút trên cùng, chúng ta hiện đã sử dụng 4 thành phần Material Design cốt lõi trong thư viện MDC-Android! Bạn có thể khám phá nhiều thành phần khác bằng cách truy cập Danh mục MDC-Android.
Mặc dù đã hoạt động đầy đủ, nhưng ứng dụng của chúng ta chưa thể hiện bất kỳ thương hiệu hoặc phong cách cụ thể nào. Trong phần MDC-103: Tuỳ chỉnh giao diện Material Design bằng màu sắc, hình dạng, độ cao và kiểu, chúng ta sẽ tuỳ chỉnh kiểu của các thành phần này để thể hiện một thương hiệu sống động, hiện đại.