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 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 và hữu ích, đồng thời có sẵn 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) để tạo trang đăng nhập: trường văn bản và nút. Bây giờ, hãy mở rộng nền tảng này bằng cách thêm chế độ đ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ẽ tạo một màn hình chính cho ứng dụng Shrine. Đây là một ứng dụng thương mại điện tử bán quần áo và đồ gia dụng. Thư mục này sẽ chứa:
- Thanh ứng dụng trên cùng
- Danh sách sản phẩm dạng lưới

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ề hoạt động phát triển Android
- Android Studio (tải xuống tại đây nếu bạn chưa có)
- Một trình mô phỏng hoặc thiết bị Android (có trong Android Studio)
- Mã mẫu (xem bước tiếp theo)
Bạn đánh giá kinh nghiệm của mình trong việc tạo ứng dụng Android ở mức nào?
Bạn đang tiếp tục từ MDC-101?
Nếu bạn đã hoàn thành MDC-101, thì mã của bạn sẽ sẵn sàng cho lớp học lập trình này. Bạn có thể chuyển đến bước 3: Thêm thanh ứng dụng trên cùng.
Bạn mới bắt đầu?
Tải ứng dụng khởi đầu của lớp học lập trình xuống
Ứng dụng khởi đầu nằm trong thư mục material-components-android-codelabs-102-starter/java. Hãy nhớ cd vào thư mục đó trước khi bắt đầu.
...hoặc sao chép từ 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) xuất hiện, hãy nhấp vào Open an existing Android Studio project (Mở một dự án hiện có trong Android Studio). Chuyển đến thư mục nơi bạn đã cài đặt mã mẫu rồi chọn java -> shrine (hoặc tìm shrine trên máy tính) để mở dự án Shrine.
- Chờ một lát để Android Studio tạo và đồng bộ hoá dự án, như được thể hiện 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 vì bạn thiếu SDK Android hoặc các công cụ bản dựng, chẳng hạn như lỗi được minh hoạ bên dưới. Hãy làm theo hướng dẫn trong Android Studio để cài đặt/cập nhật các thành phần này và đồng bộ hoá dự án của bạn.
Thêm các phần phụ thuộc của dự án
Dự án cần có một phần phụ thuộc trên thư viện hỗ trợ MDC Android. Mã mẫu mà bạn đã tải xuống có thể đã 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 để đảm bảo.
- Chuyển đến tệp
build.gradlecủa mô-đunappvà đảm bảo rằng khốidependenciescó một phần phụ thuộc vào 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 khởi đầu
|
Thành công! Bạn sẽ thấy trang đăng nhập Shrine trong 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.
Màn hình chính sẽ xuất hiện khi trang đăng nhập bị đóng, kèm theo một màn hình có nội dung "Bạn đã làm được!". Thật tuyệt! Nhưng hiện tại, người dùng của chúng ta không có hành động nào để thực hiện hoặc không biết họ đang ở đâu trong ứng dụng. Để khắc phục điều đó, hãy thêm thành phần điều hướng.
Material Design cung cấp các mẫu điều hướng giúp đảm bảo khả năng sử dụng ở mức độ cao. Một trong những thành phần điều hướng đáng chú ý nhất là thanh ứng dụng trên cùng.
Để cung cấp chế độ điều hướng và giú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á thẻ <LinearLayout> có chứa "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>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 một biểu tượng trình đơn vào biểu tượ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 nội dung sau vào thành phần XML Toolbar (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 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 thao tác vào trình đơn của thanh ứng dụng theo phương thức lập trình.
Trước tiên, hãy tạo một phương thức để thiết lập thanh công cụ. Phương thức này phải tham chiếu đến thanh công cụ bằng id và cũng tham chiếu đến hoạt động bằng getActivity(). Nếu hoạt động không phải là giá trị rỗng, hãy đặt Toolbar để dùng làm ActionBar bằng cách dùng setSupportActionBar:
ProductGridFragment.java
private void setUpToolbar(View view) {
Toolbar toolbar = view.findViewById(R.id.app_bar);
AppCompatActivity activity = (AppCompatActivity) getActivity();
if (activity != null) {
activity.setSupportActionBar(toolbar);
}
}Tiếp theo, ngay bên dưới phương thức setUpToolbar mà chúng ta vừa thêm, hãy ghi đè onCreateOptionsMenu để mở rộng nội dung của shr_toolbar_menu.xml vào thanh công cụ:
ProductGridFragment.java
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
menuInflater.inflate(R.menu.shr_toolbar_menu, menu);
super.onCreateOptionsMenu(menu, menuInflater);
}Bây giờ, hãy thêm một lệnh gọi vào phương thức setUpToolbar mà chúng ta đã thêm vào nội dung của phương thức onCreateView() bằng nội dung sau:
ProductGridFragment.java
@Override
public View onCreateView(
@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment with the ProductGrid theme
View view = inflater.inflate(R.layout.shr_product_grid_fragment, container, false);
// Set up the toolbar
setUpToolbar(view);
return view;
}Cuối cùng, hãy thêm một phương thức onCreate() vào ProductGridFragment.java. Trong phần nội dung phương thức, hãy đặt tham số của setHasOptionMenu thành true.
Phương thức này sẽ có dạng như sau:
ProductGridFragment.java
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}Đoạn mã trên đặt thanh ứng dụng trong bố cục XML của chúng ta làm Thanh hành động cho hoạt động này. Lệnh gọi lại onCreateOptionsMenu cho biết hoạt động cần sử dụng gì làm trình đơn của chúng ta. Trong trường hợp này, phương thức 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à "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 khi thay đổi, tệp ProductGridFragment.java của bạn sẽ có dạng như sau:
ProductGridFragment.java
package com.google.codelabs.mdc.java.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 android.widget.Toolbar;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
public class ProductGridFragment extends Fragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
@Override
public View onCreateView(
@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment with the ProductGrid theme
View view = inflater.inflate(R.layout.shr_product_grid_fragment, container, false);
// Set up the toolbar
setUpToolbar(view);
return view;
}
private void setUpToolbar(View view) {
Toolbar toolbar = view.findViewById(R.id.app_bar);
AppCompatActivity activity = (AppCompatActivity) getActivity();
if (activity != null) {
activity.setSupportActionBar(toolbar);
}
}
@Override
public void 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ó một biểu tượng điều hướng, một tiêu đề và hai biểu tượng thao tác ở bên phải. Thanh công cụ cũng hiển thị độ nâng bằng cách sử dụng một bóng mờ tinh tế, cho thấy thanh công cụ nằm trên một lớp khác so với nội dung.
Giờ đây, khi ứ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 các 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ó một vùng dành cho hình ảnh, một tiêu đề và một nhãn cho văn bản phụ.
Trong shr_product_grid_fragment.xml , hãy thêm nội dung sau 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 vào từ cạnh trái của màn hình, có các góc bo tròn và đổ bóng (thể hiện độ cao của thẻ). Toàn bộ khu vực này được gọi là "vùng chứa". Ngoài vùng chứa, tất cả các phần tử trong vùng chứa đều không bắt buộc.
Bạn có thể thêm các phần tử sau vào một 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ẻ mà chúng ta vừa tạo có 2 TextView (một cho tiêu đề và một cho văn bản phụ) trong một 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í các thành phần này dưới dạng một tập hợp trong lưới.
Khi có nhiều thẻ trên một màn hình, các thẻ này sẽ được nhóm lại thành một hoặc nhiều bộ sưu tập. Các thẻ trong một lưới là đồng phẳng, nghĩa là chúng có cùng độ nâng khi ở trạng thái nghỉ (trừ phi được nhấc lê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 (ở đây là NetworkImageView, cho phép chúng ta đưa hình ảnh từ một URL vào) và hai TextViews.
Tiếp theo, hãy xem ProductCardRecyclerViewAdapter mà chúng tôi đã cung cấp cho bạn. Khoá này nằm trong cùng một gói với ProductGridFragment.
ProductCardRecyclerViewAdapter.java
package com.google.codelabs.mdc.java.shrine;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.google.codelabs.mdc.java.shrine.network.ImageRequester;
import com.google.codelabs.mdc.java.shrine.network.ProductEntry;
import java.util.List;
/**
* Adapter used to show a simple grid of products.
*/
public class ProductCardRecyclerViewAdapter extends RecyclerView.Adapter<ProductCardViewHolder> {
private List<ProductEntry> productList;
private ImageRequester imageRequester;
ProductCardRecyclerViewAdapter(List<ProductEntry> productList) {
this.productList = productList;
imageRequester = ImageRequester.getInstance();
}
@NonNull
@Override
public ProductCardViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.shr_product_card, parent, false);
return new ProductCardViewHolder(layoutView);
}
@Override
public void onBindViewHolder(@NonNull ProductCardViewHolder holder, int position) {
// TODO: Put ViewHolder binding code here in MDC-102
}
@Override
public int getItemCount() {
return productList.size();
}
}Lớp bộ chuyển đổi ở trên quản lý nội dung của lưới. Để xác định xem mỗi khung hiển thị sẽ làm gì với nội dung đã cho, chúng ta sẽ sớm viết mã cho onBindViewHolder().
Trong cùng gói này, bạn cũng có thể xem ProductCardViewHolder. Lớp này lưu trữ các thành phần hiển thị ảnh hưởng đến bố cục thẻ của chúng ta, nhờ đó chúng ta có thể sửa đổi chúng sau này.
ProductCardViewHolder.java
package com.google.codelabs.mdc.java.shrine;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import android.view.View;
public class ProductCardViewHolder extends RecyclerView.ViewHolder {
public ProductCardViewHolder(@NonNull View itemView) {
super(itemView);
// TODO: Find and store views from itemView
}
}Để thiết lập lưới, trước tiên, chúng ta sẽ muố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, hãy thêm một thành phần RecyclerView vào shr_product_grid_fragment.xml bên dưới thành phần AppBarLayout XML:
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.java sau khi bạn gọi setUpToolbar(view) và trước câu lệnh return:
ProductGridFragment.java
@Override
public View onCreateView(
@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
...
setUpToolbar(view);
// Set up the RecyclerView
RecyclerView recyclerView = view.findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new GridLayoutManager(getContext(), 2, GridLayoutManager.VERTICAL, false));
ProductCardRecyclerViewAdapter adapter = new ProductCardRecyclerViewAdapter(
ProductEntry.initProductEntryList(getResources()));
recyclerView.setAdapter(adapter);
int largePadding = getResources().getDimensionPixelSize(R.dimen.shr_product_grid_spacing);
int smallPadding = getResources().getDimensionPixelSize(R.dimen.shr_product_grid_spacing_small);
recyclerView.addItemDecoration(new ProductGridItemDecoration(largePadding, smallPadding));
return view;
}Đoạn mã trên chứa các bước khởi tạo cần thiết để thiết lập một 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 động và thiết lập trình kết nối của RecyclerView.
Bây giờ, tệp ProductGridFragment.java của bạn sẽ có dạng như sau:
ProductGridFragment.java
package com.google.codelabs.mdc.java.shrine;
import android.os.Bundle;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toolbar;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.GridLayoutManager;
import com.google.codelabs.mdc.java.shrine.network.ProductEntry;
public class ProductGridFragment extends Fragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
@Override
public View onCreateView(
@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment with the ProductGrid theme
View view = inflater.inflate(R.layout.shr_product_grid_fragment, container, false);
// Set up the toolbar
setUpToolbar(view);
// Set up the RecyclerView
RecyclerView recyclerView = view.findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new GridLayoutManager(getContext(), 2, GridLayoutManager.VERTICAL, false));
ProductCardRecyclerViewAdapter adapter = new ProductCardRecyclerViewAdapter(
ProductEntry.initProductEntryList(getResources()));
recyclerView.setAdapter(adapter);
int largePadding = getResources().getDimensionPixelSize(R.dimen.shr_product_grid_spacing);
int smallPadding = getResources().getDimensionPixelSize(R.dimen.shr_product_grid_spacing_small);
recyclerView.addItemDecoration(new ProductGridItemDecoration(largePadding, smallPadding));
return view;
}
private void setUpToolbar(View view) {
Toolbar toolbar = view.findViewById(R.id.app_bar);
AppCompatActivity activity = (AppCompatActivity) getActivity();
if (activity != null) {
activity.setSupportActionBar(toolbar);
}
}
@Override
public void 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.
Các thẻ đó hiện đã xuất hiện! Hiện tại, các thành phần này chưa hiển thị gì, 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á. Hoạt động trừu tượng ViewHolder của chúng tôi giữ các khung hiển thị cho mỗi thẻ. Trong ViewHolder, hãy thêm 3 khung hiển thị như sau:
ProductCardViewHolder.java
package com.google.codelabs.mdc.java.shrine;
import androidx.recyclerview.widget.RecyclerView;
import android.view.View;
import android.widget.TextView;
import androidx.annotation.NonNull;
import com.android.volley.toolbox.NetworkImageView;
public class ProductCardViewHolder extends RecyclerView.ViewHolder {
public NetworkImageView productImage;
public TextView productTitle;
public TextView productPrice;
public ProductCardViewHolder(@NonNull View itemView) {
super(itemView);
productImage = itemView.findViewById(R.id.product_image);
productTitle = itemView.findViewById(R.id.product_title);
productPrice = itemView.findViewById(R.id.product_price);
}
}Trong trình chuyển đổi RecyclerView, trong ViewHolder,, hãy cập nhật phương thức onBindViewHolder() để đặt thông tin trên mỗi khung hiển thị:
ProductCardRecyclerViewAdapter.java
@Override
public void onBindViewHolder(@NonNull ProductCardViewHolder holder, int position) {
if (productList != null && position < productList.size()) {
ProductEntry product = productList.get(position);
holder.productTitle.setText(product.title);
holder.productPrice.setText(product.price);
imageRequester.setImageFromUrl(holder.productImage, product.url);
}
}Đoạn mã trên cho bộ chuyển đổi RecyclerView biết cách xử lý từng thẻ bằng cách sử dụng ViewHolder.
Ở đây, phương thức này đặt dữ liệu văn bản trên mỗi ViewHolder của TextView, đồng thời gọi một ImageRequester để lấy hình ảnh từ một URL. ImageRequester là một lớp mà chúng tôi cung cấp để giúp bạn thuận tiện hơn và lớp này sử dụng thư viện Volley (Đây là một chủ đề nằm ngoài phạm vi của lớp học lập trình này, nhưng bạn có thể tự do khám phá mã).
Tạo và chạy:

Các sản phẩm của chúng tôi hiện đang xuất hiện trong ứng dụng!
Ứng dụng của chúng tôi 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 một 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. Giờ đây, màn hình chính của chúng tôi đã trở nê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 trên cùng, thẻ, trường văn bản và nút, chúng ta hiện đã sử dụng 4 thành phần chính của Material Design trong thư viện MDC-Android! Bạn có thể khám phá thêm nhiều thành phần trong các thành phần Danh mục MDC-Android trong MDC Android.
Mặc dù có đầy đủ chức năng, nhưng ứng dụng của chúng ta chưa thể hiện bất kỳ thương hiệu cụ thể nào. Trong 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ữ, 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 hiện đại và sống động.
