MDC-102 Android: Cấu trúc và bố cục Material (Java)

logo_components_color_2x_web_96dp.png

Thành phần Material (MDC) giúp nhà phát triển triển khai Material Design. Do một nhóm kỹ sư và nhà thiết kế trải nghiệm người dùng tại Google tạo ra, 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 hai 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 dựa trên nền tảng này bằng cách thêm đ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 một ứng dụng có tên là Shrine, một ứng dụng thương mại điện tử chuyên bán quần áo và đồ gia dụng. Bảng này gồm có:

  • Thanh ứng dụng trên cùng
  • Danh sách lưới sản phẩm

Các thành phần MDC-Android trong lớp học lập trình này

  • Bố cục ứng dụng
  • Chế độ xem MaterialCardView

Bạn cần có

  • Kiến thức cơ bản về việc phát triển Android
  • Android Studio (tải ứng dụng xuống tại đây nếu bạn chưa có)
  • Trình mô phỏng hoặc thiết bị Android (có sẵn thông qua Android Studio)
  • Mã mẫu (xem bước tiếp theo)

Bạn xếp hạng trải nghiệm xây dựng ứng dụng Android như thế nào?

Công ty Trung cấp Đặc biệt

Tiếp tục từ MDC-101?

Nếu bạn đã hoàn tất MDC-101, mã của bạn phải sẵn sàng cho lớp học lập trình này. Bạn có thể chuyển sang bước 3: Thêm thanh ứng dụng trên cùng.

Thiết lập từ đầu?

Tải ứng dụng Lớp học lập trình dành cho người mới bắt đầu

Tải ứng dụng dành cho người mới bắt đầu

Ứng dụng khởi động 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 đường liên kết 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ã dành cho người mới bắt đầu trong Android Studio

  1. Sau khi trình hướng dẫn thiết lập hoàn tất và cửa sổ Chào mừng bạn đến với Android Studio, hãy nhấp vào 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 và chọn java -> Temple (hoặc tìm shrine trên máy tính) để mở dự án Temple.
  2. Đợi trong giây lát để Android Studio tạo và đồng bộ hóa dự án, theo như chỉ báo hoạt động ở cuối cửa sổ Android Studio.
  3. Tại thời điểm này, Android Studio có thể gặp một số lỗi bản dựng vì bạn thiếu SDK Android hoặc công cụ tạo, chẳng hạn như công cụ hiển thị bên dưới. Làm theo hướng dẫn trong Android Studio để cài đặt/cập nhật và đồng bộ hóa dự án này.

Thêm các phần phụ thuộc dự án

Dự án cần phần phụ thuộc trên thư viện hỗ trợ MDC Android. Mã mẫu mà bạn đã tải xuống phải có 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.

  1. Chuyển đến tệp build.gradle mô-đun app và đảm bảo rằng khối dependencies bao gồm phần phụ thuộc trên MDC Android:
api 'com.google.android.material:material:1.1.0-alpha06'
  1. (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ộ hóa 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 dành cho người mới bắt đầu

  1. Đảm bảo rằng cấu hình bản dựng ở bên trái nút Chạy / Phátapp.
  2. Nhấn vào nút Chạy/Phát màu xanh lục để tạo và chạy ứng dụng.
  3. Trong cửa sổ Chọn triển khai mục tiêu, nếu bạn đã có thiết bị Android được liệt kê trong các thiết bị có sẵn, hãy chuyển đến Bước 8. Nếu không, hãy nhấp vào Create New Device Device (Tạo thiết bị ảo mới).
  4. Trong màn hình Chọn phần cứng, hãy chọn điện thoại như Pixel 2, sau đó nhấp vào Tiếp theo.
  5. Trong màn hình Hệ thống hình ảnh, hãy chọn một phiên bản Android gần đây, tốt nhất là cấp độ API cao nhất. Nếu chưa cài đặt thì hãy nhấp vào đường liên kết Tải xuống được hiển thị và hoàn tất việc tải xuống.
  6. Nhấp vào Next (Tiếp theo)
  7. Trên màn hình Thiết bị ảo Android (AVD), hãy giữ nguyên các chế độ cài đặt rồi nhấp vào Hoàn tất.
  8. Chọn thiết bị Android từ hộp thoại mục tiêu triển khai.
  9. Nhấp vào Ok.
  10. Android Studio tạo ứng dụng, triển khai và tự động mở ứng dụng trên thiết bị đích.

Thành công! Bạn sẽ thấy trang đăng nhập Đền thờ từ lớp học lập trình MDC-101.

Bây giờ, màn hình đăng nhập có vẻ ổn, hãy để ứng dụng điền một số sản phẩm vào ứng dụng.

Màn hình chính sẽ hiển thị khi trang đăng nhập bị loại bỏ, với màn hình có chữ "quot;Bạn đã làm được rồi!&quot! Thật tuyệt! Nhưng giờ đây, người dùng của chúng tôi không có hành động nào để thực hiện hoặc bất kỳ cảm giác nào về vị trí của họ trong ứng dụng. Để giúp họ làm việc đó, hãy thêm điều hướng.

Material Design cung cấp các mẫu điều hướng đảm bảo khả năng hữu dụng 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.

Để đ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 thanh ứng dụng trên cùng.

Thêm tiện ích AppBar

Trong shr_product_grid_fragment.xml, hãy xóa thẻ <LinearLayout> chứa "Bạn đã làm được rồi!&quot! TextView và thay thế bằng:

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 phải 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 danh sách của chúng tôi.

Thêm biểu tượng đi theo chỉ dẫn

Khi vẫn ở shr_product_grid_fragment.xml, hãy thêm nội dung sau đây 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 phải 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 tôi 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 của nhóm 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 sẽ lấy thông tin tham chiếu đến thanh công cụ bằng cách sử dụng id, đồng thời lấy thông tin tham chiếu đến hoạt động bằng cách sử dụng getActivity(). Nếu hoạt động là null, hãy đặt Toolbar thành ActionBar dưới 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 tôi vừa thêm, hãy ghi đè onCreateOptionsMenu để tăng cườ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 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() như 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 phương thức onCreate() vào ProductGridFragment.java. Trong phần nội dung của phương thức, hãy đặt thông số của setHasOptionMenutrue.

Phương thức phải có dạng như sau:

ProductGridFragment.java

@Override
public void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setHasOptionsMenu(true);
}

Mã ở trên đặt thanh ứng dụng trong bố cục XML của chúng ta sẽ là Thanh hành động cho hoạt động này. Lệnh gọi lại onCreateOptionsMenu cho hoạt động này dùng những gì trên trình đơn. Trong trường hợp này, mục này sẽ đưa 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: "Search" và "Filter".

shr_bashi_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.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 và chạy. Màn hình chính 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 ở phía bên phải. Thanh công cụ cũng hiển thị độ cao bằng cách sử dụng bóng tối, nó hiển thị độ cao trên một lớp khác với nội dung.

Ứ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 thẻ vào thẻ.

Thêm thẻ

Hãy bắt đầu bằng cách thêm một thẻ vào bên dưới thanh ứng dụng trên cùng. Thẻ phải có vùng cho hình ảnh, tiêu đề và nhãn cho văn bản phụ.

Trong shr_product_grid_fragment.xml, hãy thêm các mục sau vào 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ẻ nằm ở cạnh bên trái của màn hình, có các góc được bo tròn và bóng đổ (hiển thị độ cao của thẻ). Toàn bộ khu vực này được gọi là "container." Ngoài chính 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 thành phần 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ụ, dấu phân cách, thậm chí là các nút và biểu tượng. Ví dụ: thẻ chúng tôi 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ẻ.

Các thẻ thường xuất hiện trong 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ẽ trình bày chúng dưới dạng một tập hợp trong lưới.

Khi có nhiều thẻ trong một màn hình, những 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à một bộ đồng vị, có nghĩa là các thẻ này có cùng độ cao nghỉ ngơi với nhau (trừ khi đượ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 (ở đây là NetworkImageView, cho phép chúng ta kèm theo 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. Trong gó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 những việc mà mỗi chế độ xem nên làm với nội dung cụ thể, chúng tôi 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ữ các chế độ xem ảnh hưởng đến bố cục thẻ của chúng ta, do đó, chúng ta có thể sửa đổi các chế độ xem đó sau.

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 tôi muốn xóa 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 tôi. Trong trường hợp này, hãy 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 phải 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 tạo 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 chạy cần thiết để thiết lập RecyclerView. Quá trình này bao gồm việc đặt trình quản lý bố cục của RecyclerView, cũng như khởi tạo và đặt bộ chuyển đổi của RecyclerView\39;

Tệp ProductGridFragment.java của bạn giờ đây 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 và chạy.

Thẻ đã có trên thẻ! Họ 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á. Bản trừu tượng ViewHolder của chúng tôi chứa các chế độ xem cho mỗi thẻ. Trong ViewHolder, hãy thêm ba chế độ xem 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 bộ chuyển đổi RecyclerView\u9; trong ViewHolder,, hãy cập nhật phương thức onBindViewHolder() để đặt thông tin trên mỗi chế độ xem:

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 của RecyclerView biết phải làm gì với mỗi thẻ bằng ViewHolder.

Tại đây, hệ thống sẽ đặt dữ liệu văn bản trên từng TextView của ViewHolder và gọi ImageRequester để lấy hình ảnh từ một URL. ImageRequester là một lớp học mà chúng tôi đã cung cấp để bạn tiện tham khảo và sử dụng thư viện Volley (Đó là 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ự mình khám phá mã này.

Tạo và chạy:

Các sản phẩm của chúng tôi hiện đang hiển thị 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 các sản phẩm có thể xem được. Chỉ trong vài dòng mã, chúng tôi đã thêm một thanh ứng dụng hàng đầu có tiêu đề và ba 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à hoạt động với cấu trúc cơ bản và nội dung hữu ích.

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, giờ đây, chúng tôi đã sử dụng bốn thành phần Material Design thiết kế cốt lõi từ thư viện MDC-Android! Bạn có thể khám phá thêm nhiều thành phần khác trong thành phần Danh mục MDC-Android trong MDC Android.

Mặc dù ứng dụng này có đầy đủ chức năng, nhưng ứng dụng của chúng tôi chưa thể hiện bất kỳ thương hiệu cụ thể nào. Trong MDC-103: Material Design Cùng với màu sắc, hình dạng, độ cao và loại, chúng tôi sẽ tùy chỉnh kiểu dáng của các thành phần này để thể hiện thương hiệu hiện đại, sống động.

Tôi đã hoàn thành được lớp học lập trình này với lượng thời gian và công sức hợp lý

Hoàn toàn đồng ý Đồng ý Bình thường Không đồng ý Hoàn toàn không đồng ý

Tôi muốn tiếp tục sử dụng các Thành phần Material trong tương lai

Hoàn toàn đồng ý Đồng ý Bình thường Không đồng ý Hoàn toàn không đồng ý