Material Components (MDC) ช่วยให้นักพัฒนาแอปใช้งาน Material Design ได้ MDC สร้างขึ้นโดยทีมวิศวกรและนักออกแบบ UX ที่ Google โดยมีคอมโพเนนต์ UI ที่สวยงามและใช้งานได้หลายสิบรายการ และพร้อมใช้งานสำหรับ Android, iOS, เว็บ และ Flutter material.io/develop |
ใน Codelab MDC-101 คุณใช้คอมโพเนนต์ Material (MDC) 2 รายการเพื่อสร้างหน้าเข้าสู่ระบบ ได้แก่ ช่องข้อความและปุ่ม ตอนนี้มาต่อยอดจากพื้นฐานนี้ด้วยการเพิ่มการนำทาง โครงสร้าง และข้อมูลกัน
สิ่งที่คุณจะสร้าง
ในโค้ดแล็บนี้ คุณจะได้สร้างหน้าจอหลักสำหรับแอปชื่อ Shrine ซึ่งเป็นแอปอีคอมเมิร์ซที่ขายเสื้อผ้าและของใช้ในบ้าน ซึ่งประกอบด้วย
- แถบแอปด้านบน
- รายการผลิตภัณฑ์แบบตารางกริด

คอมโพเนนต์ MDC-Android ใน Codelab นี้
- AppBarLayout
- MaterialCardView
สิ่งที่ต้องมี
- ความรู้พื้นฐานเกี่ยวกับการพัฒนาแอป Android
- Android Studio (ดาวน์โหลดที่นี่หากยังไม่มี)
- โปรแกรมจำลองหรืออุปกรณ์ Android (พร้อมใช้งานผ่าน Android Studio)
- โค้ดตัวอย่าง (ดูขั้นตอนถัดไป)
คุณจะให้คะแนนระดับประสบการณ์ในการสร้างแอป Android เท่าใด
หากเคยเรียน MDC-101 มาแล้ว
หากคุณทำ MDC-101 เสร็จแล้ว โค้ดของคุณควรพร้อมสำหรับโค้ดแล็บนี้ คุณข้ามไปยังขั้นตอนที่ 3: เพิ่มแถบแอปด้านบนได้
หากเพิ่งเริ่มต้น
ดาวน์โหลดแอป Codelab สำหรับผู้เริ่มต้น
แอปเริ่มต้นอยู่ในไดเรกทอรี material-components-android-codelabs-102-starter/java อย่าลืม cd เข้าไปในไดเรกทอรีนั้นก่อนเริ่มต้น
...หรือโคลนจาก GitHub
หากต้องการโคลนโค้ดแล็บนี้จาก GitHub ให้เรียกใช้คำสั่งต่อไปนี้
git clone https://github.com/material-components/material-components-android-codelabs cd material-components-android-codelabs/ git checkout 102-starter
โหลดโค้ดเริ่มต้นใน Android Studio
- เมื่อวิซาร์ดการตั้งค่าเสร็จสิ้นและหน้าต่างยินดีต้อนรับสู่ Android Studio ปรากฏขึ้น ให้คลิกเปิดโปรเจ็กต์ Android Studio ที่มีอยู่ ไปที่ไดเรกทอรีที่คุณติดตั้งโค้ดตัวอย่าง แล้วเลือก java -> shrine (หรือค้นหา shrine ในคอมพิวเตอร์) เพื่อเปิดโปรเจ็กต์ Shrine
- รอสักครู่เพื่อให้ Android Studio สร้างและซิงค์โปรเจ็กต์ ดังที่แสดงโดยตัวบ่งชี้กิจกรรมที่ด้านล่างของหน้าต่าง Android Studio
- ในขั้นตอนนี้ Android Studio อาจแสดงข้อผิดพลาดในการสร้างบางอย่างเนื่องจากคุณไม่มี Android SDK หรือเครื่องมือบิลด์ เช่น เครื่องมือที่แสดงด้านล่าง ทำตามวิธีการใน Android Studio เพื่อติดตั้ง/อัปเดตไลบรารีเหล่านี้และซิงค์โปรเจ็กต์
เพิ่มการพึ่งพาโปรเจ็กต์
โปรเจ็กต์ต้องมีทรัพยากร Dependency ในไลบรารีการรองรับ MDC Android โค้ดตัวอย่างที่คุณดาวน์โหลดควรมีรายการการอ้างอิงนี้อยู่แล้ว แต่แนวทางปฏิบัติแนะนำคือการทำตามขั้นตอนต่อไปนี้เพื่อให้แน่ใจ
- ไปที่ไฟล์
build.gradleของโมดูลappและตรวจสอบว่าบล็อกdependenciesมีการอ้างอิง MDC Android
api 'com.google.android.material:material:1.1.0-alpha06'
- (ไม่บังคับ) หากจำเป็น ให้แก้ไขไฟล์
build.gradleเพื่อเพิ่มการอ้างอิงต่อไปนี้และซิงค์โปรเจ็กต์
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'
}เรียกใช้แอปเริ่มต้น
|
สำเร็จ! คุณควรเห็นหน้าเข้าสู่ระบบ Shrine จาก Codelab MDC-101

ตอนนี้หน้าจอเข้าสู่ระบบดูดีแล้ว มาป้อนข้อมูลผลิตภัณฑ์บางอย่างลงในแอปกัน
หน้าจอหลักจะปรากฏขึ้นเมื่อปิดหน้าเข้าสู่ระบบ โดยจะมีหน้าจอที่ระบุว่า "คุณทำสำเร็จแล้ว!" เยี่ยมเลย แต่ตอนนี้ผู้ใช้ไม่มีการดำเนินการใดๆ หรือไม่รู้ว่าตัวเองอยู่ที่ส่วนใดในแอป เรามาเพิ่มการนำทางเพื่อช่วยในเรื่องนี้กัน
Material Design มีรูปแบบการนำทางที่ช่วยให้มั่นใจได้ถึงความสามารถในการใช้งานในระดับสูง คอมโพเนนต์การนำทางที่โดดเด่นที่สุดอย่างหนึ่งคือแถบแอปด้านบน
มาเพิ่มแถบแอปด้านบนเพื่อช่วยในการนำทางและให้ผู้ใช้เข้าถึงการดำเนินการอื่นๆ ได้อย่างรวดเร็วกัน
เพิ่มวิดเจ็ต AppBar
ใน shr_product_grid_fragment.xml ให้ลบแท็ก <LinearLayout> ที่มีข้อความ "คุณทำได้แล้ว!" TextView แล้วแทนที่ด้วยข้อความต่อไปนี้
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 ควรมีลักษณะดังนี้
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>แถบแอปหลายแถบมีปุ่มข้างชื่อ มาเพิ่มไอคอนเมนูลงในของเรากัน
เพิ่มไอคอนการนำทาง
ขณะที่ยังอยู่ใน shr_product_grid_fragment.xml ให้เพิ่มข้อมูลต่อไปนี้ลงในคอมโพเนนต์ XML ของ Toolbar (ซึ่งคุณเพิ่งเพิ่มลงในเลย์เอาต์)
shr_product_grid_fragment.xml
app:navigationIcon="@drawable/shr_menu"shr_product_grid_fragment.xml ควรมีลักษณะดังนี้
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>เพิ่มปุ่มการทำงานและจัดรูปแบบแถบแอปด้านบน
นอกจากนี้ คุณยังเพิ่มปุ่มที่ด้านท้ายของแถบแอปได้ด้วย ใน Android ปุ่มเหล่านี้เรียกว่าปุ่มการดำเนินการ
เราจะจัดรูปแบบแถบแอปด้านบนและเพิ่มปุ่มการทำงานลงในเมนูโดยใช้โปรแกรม
ก่อนอื่น มาสร้างเมธอดเพื่อตั้งค่าแถบเครื่องมือกัน เมธอดควรรับการอ้างอิงไปยังแถบเครื่องมือโดยใช้ id และรับการอ้างอิงไปยังกิจกรรมโดยใช้ getActivity() หากกิจกรรมไม่ใช่ค่าว่าง ให้ตั้งค่า Toolbar ที่จะใช้เป็น ActionBar โดยใช้ 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);
}
}จากนั้นใต้setUpToolbarเมธอดที่เราเพิ่งเพิ่มไป ให้แทนที่ onCreateOptionsMenu เพื่อขยายเนื้อหาของ shr_toolbar_menu.xml ลงในแถบเครื่องมือ
ProductGridFragment.java
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
menuInflater.inflate(R.menu.shr_toolbar_menu, menu);
super.onCreateOptionsMenu(menu, menuInflater);
}ตอนนี้ให้เพิ่มการเรียกใช้เมธอด setUpToolbar ที่เราเพิ่มลงในเนื้อหาของเมธอด onCreateView() โดยใช้ข้อมูลต่อไปนี้
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;
}สุดท้าย ให้เพิ่มonCreate()วิธีการไปยัง ProductGridFragment.java ในส่วนเนื้อหาของเมธอด ให้ตั้งค่าพารามิเตอร์ของ setHasOptionMenu เป็น true
วิธีการควรมีลักษณะดังนี้
ProductGridFragment.java
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}โค้ดด้านบนจะตั้งค่าแถบแอปจากเลย์เอาต์ XML ให้เป็นแถบการดำเนินการสำหรับกิจกรรมนี้ Callback onCreateOptionsMenu จะบอกกิจกรรมว่าจะใช้สิ่งใดเป็นเมนูของเรา ในกรณีนี้ ระบบจะวางรายการในเมนูจาก R.menu.shr_toolbar_menu ลงในแถบแอป
ไฟล์เมนูมี 2 รายการ ได้แก่ "ค้นหา" และ "กรอง"
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>หลังจากทำการเปลี่ยนแปลงเหล่านั้นแล้ว ไฟล์ ProductGridFragment.java ควรมีลักษณะดังนี้
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);
}
}สร้างและเรียกใช้ หน้าจอหลักควรมีลักษณะดังนี้

ตอนนี้แถบเครื่องมือมีไอคอนการนำทาง ชื่อ และไอคอนการดำเนินการ 2 รายการทางด้านขวา แถบเครื่องมือยังแสดงระดับความสูงโดยใช้เงาที่มองเห็นได้เล็กน้อย ซึ่งแสดงให้เห็นว่าแถบเครื่องมืออยู่คนละเลเยอร์กับเนื้อหา
ตอนนี้แอปของเรามีโครงสร้างแล้ว มาจัดระเบียบเนื้อหาโดยวางไว้ในการ์ดกัน
เพิ่มบัตร
มาเริ่มกันด้วยการเพิ่มการ์ด 1 ใบใต้แถบแอปด้านบน การ์ดควรมีพื้นที่สำหรับรูปภาพ ชื่อ และป้ายกำกับสำหรับข้อความรอง
ใน shr_product_grid_fragment.xml ให้เพิ่มรายการต่อไปนี้ใต้ 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>สร้างและเรียกใช้

ในตัวอย่างนี้ คุณจะเห็นว่าการ์ดอยู่ห่างจากขอบด้านซ้ายของหน้าจอ และมีการ์ดมีมุมโค้งมนและเงา (ซึ่งแสดงถึงระดับความสูงของการ์ด) ทั้งพื้นที่เรียกว่า "คอนเทนเนอร์" นอกเหนือจากคอนเทนเนอร์แล้ว องค์ประกอบทั้งหมดภายในคอนเทนเนอร์เป็นค่าที่ไม่บังคับ
คุณเพิ่มองค์ประกอบต่อไปนี้ลงในคอนเทนเนอร์ได้ ได้แก่ ข้อความส่วนหัว ภาพปกหรือรูปโปรไฟล์ ข้อความส่วนหัวย่อย เส้นแบ่ง รวมถึงปุ่มและไอคอน เช่น การ์ดที่เราเพิ่งสร้างมี TextView 2 รายการ (รายการหนึ่งสำหรับชื่อและอีกรายการหนึ่งสำหรับข้อความรอง) ใน LinearLayout ซึ่งจัดแนวไว้ที่ด้านล่างของการ์ด
โดยปกติแล้ว การ์ดจะแสดงในคอลเล็กชันพร้อมกับการ์ดอื่นๆ ในส่วนถัดไปของ Codelab นี้ เราจะจัดวางเป็นคอลเล็กชันในตารางกริด
เมื่อมีการ์ดหลายใบในหน้าจอ ระบบจะจัดกลุ่มการ์ดเหล่านั้นไว้ด้วยกันเป็นคอลเล็กชันเดียวหรือหลายคอลเล็กชัน การ์ดในตารางจะอยู่บนระนาบเดียวกัน ซึ่งหมายความว่าการ์ดจะมีความสูงเท่ากัน (เว้นแต่จะมีการหยิบหรือลากการ์ด แต่เราจะไม่พูดถึงในโค้ดแล็บนี้)
ตั้งค่าตารางการ์ด
ดูshr_product_card.xmlไฟล์ที่เราจัดเตรียมไว้ให้คุณ
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>เลย์เอาต์การ์ดนี้มีการ์ดที่มีรูปภาพ (ในที่นี้คือ NetworkImageView ซึ่งช่วยให้เราใส่รูปภาพจาก URL ได้) และ TextViews 2 รายการ
จากนั้นดูProductCardRecyclerViewAdapterที่เราจัดเตรียมไว้ให้คุณ โดยจะอยู่ในแพ็กเกจเดียวกับ 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();
}
}คลาสอะแดปเตอร์ด้านบนจะจัดการเนื้อหาของตารางกริด เราจะเขียนโค้ดสำหรับ onBindViewHolder() ในเร็วๆ นี้เพื่อกำหนดว่าแต่ละมุมมองควรทำอะไรกับเนื้อหาที่ได้รับ
ในแพ็กเกจเดียวกัน คุณยังดู ProductCardViewHolder ได้ด้วย คลาสนี้จะจัดเก็บมุมมองที่มีผลต่อเลย์เอาต์การ์ด เพื่อให้เราแก้ไขได้ในภายหลัง
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
}
}หากต้องการตั้งค่าตารางกริด เราจะต้องนำตัวยึดตำแหน่ง MaterialCardView ออกจาก shr_product_grid_fragment.xml ก่อน จากนั้นคุณควรเพิ่มคอมโพเนนต์ที่แสดงตารางการ์ด ในกรณีนี้ ให้เพิ่มคอมโพเนนต์ RecyclerView ลงใน shr_product_grid_fragment.xml ใต้คอมโพเนนต์ 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 ควรมีลักษณะดังนี้
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>สุดท้ายใน onCreateView() ให้เพิ่มRecyclerViewโค้ดการเริ่มต้นลงใน ProductGridFragment.java หลังจากเรียกใช้ setUpToolbar(view) และก่อนคำสั่ง 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;
}ข้อมูลโค้ดข้างต้นมีขั้นตอนการเริ่มต้นที่จำเป็นในการตั้งค่า RecyclerView ซึ่งรวมถึงการตั้งค่าเครื่องมือจัดการเลย์เอาต์ของ RecyclerView รวมถึงการเริ่มต้นและตั้งค่าอแดปเตอร์ของ RecyclerView
ตอนนี้ไฟล์ ProductGridFragment.java ควรมีลักษณะดังนี้
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);
}
}สร้างและเรียกใช้
ตอนนี้การ์ดพร้อมให้ใช้งานแล้ว ตอนนี้ยังไม่มีอะไรแสดง เรามาเพิ่มข้อมูลผลิตภัณฑ์กัน
เพิ่มรูปภาพและข้อความ
เพิ่มรูปภาพ ชื่อผลิตภัณฑ์ และราคาสำหรับการ์ดแต่ละใบ ViewHolderการแยกส่วนของเราจะเก็บมุมมองของการ์ดแต่ละใบ ใน ViewHolder ให้เพิ่มมุมมองทั้ง 3 ดังนี้
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);
}
}ในอแดปเตอร์ของ RecyclerView ใน ViewHolder, ให้อัปเดตเมธอด onBindViewHolder() เพื่อตั้งค่าข้อมูลในแต่ละมุมมอง
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);
}
}โค้ดด้านบนจะบอกอะแดปเตอร์ของ RecyclerView ว่าจะทำอะไรกับการ์ดแต่ละใบโดยใช้ ViewHolder
ในที่นี้จะตั้งค่าข้อมูลข้อความใน ViewHolderTextView แต่ละรายการ และเรียกใช้ ImageRequester เพื่อรับรูปภาพจาก URL ImageRequester เป็นคลาสที่เราจัดเตรียมไว้เพื่อความสะดวกของคุณ และใช้ไลบรารี Volley (ซึ่งเป็นหัวข้อที่อยู่นอกขอบเขตของโค้ดแล็บนี้ แต่คุณสามารถสำรวจโค้ดได้ด้วยตนเอง)
สร้างและเรียกใช้

ตอนนี้ผลิตภัณฑ์ของเราแสดงในแอปแล้ว
แอปของเรามีขั้นตอนพื้นฐานที่นำผู้ใช้จากหน้าจอเข้าสู่ระบบไปยังหน้าจอหลัก ซึ่งผู้ใช้สามารถดูผลิตภัณฑ์ได้ เราเพิ่มแถบแอปด้านบนที่มีชื่อและปุ่ม 3 ปุ่ม รวมถึงตารางการ์ดเพื่อนำเสนอเนื้อหาของแอปด้วยโค้ดเพียงไม่กี่บรรทัด ตอนนี้หน้าจอหลักของเราเรียบง่ายและใช้งานได้จริง โดยมีโครงสร้างพื้นฐานและเนื้อหาที่ดำเนินการได้
ขั้นตอนถัดไป
ตอนนี้เราได้ใช้คอมโพเนนต์หลัก 4 รายการของ Material Design จากไลบรารี MDC-Android แล้ว ได้แก่ แถบแอปด้านบน การ์ด ช่องข้อความ และปุ่ม คุณดูคอมโพเนนต์เพิ่มเติมได้ในแคตตาล็อก MDC-Android คอมโพเนนต์ใน MDC Android
แม้ว่าแอปจะทำงานได้อย่างเต็มที่ แต่ก็ยังไม่ได้แสดงแบรนด์ใดแบรนด์หนึ่ง ใน MDC-103: Material Design Theming with Color, Shape, Elevation and Type เราจะปรับแต่งสไตล์ของคอมโพเนนต์เหล่านี้เพื่อแสดงถึงแบรนด์ที่สดใสและทันสมัย
