1. מבוא
Material Components (MDC) עוזר למפתחים להטמיע Material Design. MDC נוצר על ידי צוות של מהנדסים ומעצבי חוויית משתמש ב-Google, והוא כולל עשרות רכיבי ממשק משתמש יפים ופונקציונליים. הוא זמין ל-Android, ל-iOS, לאינטרנט ול-Flutter.material.io/develop |
בקודלאב MDC-101 השתמשתם בשני רכיבי Material Components (MDC) כדי ליצור דף כניסה: שדות טקסט ולחצנים. עכשיו נרחיב את הבסיס הזה על ידי הוספת ניווט, מבנה ונתונים.
מה תפַתחו
בסדנת הקוד הזו תלמדו ליצור מסך בית לאפליקציה בשם Shrine, אפליקציית מסחר אלקטרוני שמוכרת בגדים ומוצרים לבית. היא תכלול את הפרטים הבאים:
- סרגל אפליקציה בחלק העליון
- רשימת מוצרים בתצוגת רשת
רכיבי MDC-Android ב-Codelab הזה
- AppBarLayout
- MaterialCardView
מה צריך להכין
- ידע בסיסי בפיתוח Android
- Android Studio (אפשר להוריד אותו כאן אם עדיין אין לך אותו)
- מכשיר או אמולטור של Android (זמין דרך Android Studio)
- הקוד לדוגמה (מידע נוסף מופיע בשלב הבא)
מה מידת הניסיון שלך בפיתוח אפליקציות ל-Android?
2. הגדרת סביבת הפיתוח
ממשיכים לעבור מ-MDC-101?
אם השלמתם את קורס MDC-101, הקוד שלכם אמור להיות מוכן לקודלאב הזה. אפשר לדלג לשלב 3: הוספת סרגל אפליקציות בחלק העליון.
מתחילים מאפס?
להורדת האפליקציה לתחילת פעולה של Codelab
האפליקציה לתחילת הפעולה נמצאת בספרייה material-components-android-codelabs-102-starter/java
. חשוב להקליד cd
בספרייה הזו לפני שמתחילים.
...או לשכפל אותו מ-GitHub
כדי לשכפל את ה-Codelab הזה מ-GitHub, מריצים את הפקודות הבאות:
git clone https://github.com/material-components/material-components-android-codelabs cd material-components-android-codelabs/ git checkout 102-starter
טוענים את הקוד לתחילת הפעולה ב-Android Studio
- בסיום אשף ההגדרה, כשמופיעה החלון Welcome to Android Studio, לוחצים על Open an existing Android Studio project. עוברים לספרייה שבה התקנתם את קוד הדוגמה ובוחרים באפשרות java -> shrine (או מחפשים במחשב את shrine) כדי לפתוח את הפרויקט Shrine.
- ממתינים כמה רגעים עד ש-Android Studio תבנה ותסנכרן את הפרויקט, כפי שמוצג במדדי הפעילות בחלק התחתון של חלון Android Studio.
- בשלב הזה, ייתכן שיוצגו ב-Android Studio חלק משגיאות ה-build כי ה-SDK של Android או כלי ה-build חסרים לכם, כמו זה שמוצג למטה. כדי להתקין או לעדכן אותם ולסנכרן את הפרויקט, פועלים לפי ההוראות ב-Android Studio.
הוספת יחסי תלות לפרויקט
הפרויקט צריך להיות תלוי בספריית התמיכה של 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' }
הפעלת אפליקציה לתחילת פעולה
|
הצלחת! דף ההתחברות לאתר אמור להופיע ב-MDC-101 Codelab.
עכשיו, אחרי שמסך הכניסה נראה טוב, נוסיף לאפליקציה כמה מוצרים.
3. הוספת סרגל אפליקציה עליון
מסך הבית מוצג אחרי שסוגרים את דף ההתחברות, עם המסך 'הצלחת!'. נהדר! אבל עכשיו למשתמשים שלנו אין פעולות שהם יכולים לבצע, ואין להם מושג איפה הוא נמצא באפליקציה. כדי לעזור בעניין הזה, נוסיף ניווט.
עיצוב חדשני (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()
. אם הפעילות לא מוגדרת כ-null, צריך להגדיר את 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);
}
עכשיו מוסיפים קריאה ל-method setUpToolbar
שהוספנו לתוכן של method 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
. בגוף ה-method, מגדירים את הפרמטר setHasOptionMenu
כ-true
.
השיטה אמורה להיראות כך:
ProductGridFragment.java
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
הקוד שלמעלה מגדיר את שורת האפליקציות מתבנית ה-XML שלנו בתור שורת הפעולות לפעילות הזו. קריאה חוזרת onCreateOptionsMenu
מעדכנת את הפעילות במה להשתמש בתור התפריט שלנו. במקרה כזה, אפשרויות התפריט מ-R.menu.shr_toolbar_menu
יופיעו בסרגל האפליקציה.
קובץ התפריט מכיל שני פריטים: 'חיפוש' ו'סינון'.
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);
}
}
פיתוח והרצה. מסך הבית אמור להיראות כך:
עכשיו סרגל הכלים כולל סמל ניווט, כותרת ושני סמלי פעולות בצד שמאל. בסרגל הכלים מוצגת גם תצוגה של הגובה באמצעות צללית עדינה, שמראה שהוא נמצא בשכבה שונה מהתוכן.
4. הוספת כרטיס
עכשיו, אחרי שיש לאפליקציה שלנו מבנה כלשהו, נארגן את התוכן על ידי הצבתו בכרטיסים.
הוספת כרטיס
כדי להתחיל, מוסיפים כרטיס אחד מתחת לסרגל האפליקציות העליון. בכרטיס צריך להיות אזור לתמונה, כותרת ותווית לטקסט משני.
ב-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
(אחת לכותרת ואחת לטקסט משני) בתוך LinearLayout
, שממולאות בחלק התחתון של הכרטיס.
בדרך כלל הכרטיסים מוצגים באוסף יחד עם כרטיסים אחרים. בקטע הבא של סדנת הקוד הזו, נציג אותם כקולקציה בתוך רשת.
5. יצירת רשת של כרטיסים
כשמוצגים כמה כרטיסים במסך, הם מקובצים יחד באוסף אחד או יותר. כרטיסים ברשת הם על קו מישור
הגדרת פריסת הכרטיסים
כדאי לעיין בקובץ 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
.
בשלב הבא, כדאי לעיין ב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
}
}
כדי להגדיר את הרשת שלנו, קודם אנחנו רוצים להסיר את ה-placeholder MaterialCardView
מ-shr_product_grid_fragment.xml
. בשלב הבא צריך להוסיף את הרכיב שמייצג את רשת הכרטיסים. במקרה כזה, מוסיפים רכיב RecyclerView ל-shr_product_grid_fragment.xml
מתחת לרכיב ה-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
אמור להיראות כך:
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
שלנו, מוסיפים את שלוש התצוגות באופן הבא:
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
.
כאן הוא מגדיר את נתוני הטקסט בכל אחד מה-TextView
של ViewHolder
, וקורא ל-ImageRequester
כדי לקבל תמונה מכתובת URL. ImageRequester
היא כיתה שסיפקנו לנוחיותכם, והיא משתמשת בספרייה Volley
(זהו נושא מחוץ להיקף של Codelab הזה, אבל אתם יכולים לבדוק את הקוד בעצמכם).
יצירה והפעלה:
המוצרים שלנו מוצגים עכשיו באפליקציה!
6. Recap
באפליקציה שלנו יש תהליך בסיסי שמעביר את המשתמש ממסך ההתחברות למסך הבית, שבו ניתן לצפות במוצרים. בעזרת כמה שורות קוד, הוספנו סרגל אפליקציה בחלק העליון עם כותרת ושלושה לחצנים, ותצוגת רשת של כרטיסים להצגת התוכן של האפליקציה. מסך הבית שלנו עכשיו פשוט ופונקציונלי, עם מבנה בסיסי ותוכן פרקטי.
השלבים הבאים
עם הסרגל העליון של האפליקציה, הכרטיס, שדה הטקסט והלחצן, השתמשנו עכשיו בארבעה רכיבי ליבה של Material Design מהספרייה MDC-Android! אפשר למצוא עוד רכיבים בקטלוג MDC-Android רכיבים ב-MDC Android.
האפליקציה שלנו פונקציונלית לחלוטין, אבל היא עדיין לא מייצגת מותג מסוים. במשחק MDC-103: עיצוב חומרים בעיצוב חדשני עם צבע, צורה, גובה וסוג, נתאים אישית את הסגנון של הרכיבים האלה כדי לבטא מותג מודרני ותוסס.