MDC-102 Android: بنية المواد وتنسيقها (Java)

logo_components_color_2x_web_96dp.png

تساعد المكونات المادية (MDC) مطوّري البرامج على تنفيذ التصميم المتعدد الأبعاد. أنشأ فريق من المهندسين ومصمِّمي تجارب المستخدمين في Google العشرات من مكوّنات واجهة المستخدم الجميلة والعملية، وهي متوفّرة لنظامَي التشغيل Android وiOS والويب وFltter.

material.io/develop

في الترميز الدرس التطبيقي MDC-101، استخدمت مكونين ماديين (MDC) لإنشاء صفحة تسجيل الدخول: حقول النص والأزرار. والآن، سنعمل على توسيع نطاق هذه القاعدة من خلال إضافة عناصر التنقّل والبنية والبيانات.

العناصر التي سيتم إنشاؤها

في هذا الدرس التطبيقي حول الترميز، ستنشئ شاشة رئيسية لتطبيق يُسمى Shrine، وهو تطبيق للتجارة الإلكترونية يبيع الملابس والسلع المنزلية. ستحتوي على:

  • شريط أهم التطبيقات
  • قائمة منتجات

مكوّنات MDC-Android في هذا الدرس التطبيقي حول الترميز

  • تنسيق AppBar
  • عرض MaterialCard

المتطلبات اللازمة

  • معرفة أساسية بتطوير تطبيقات Android
  • استوديو Android (يمكنك تنزيله هنا إذا لم يكن لديك حاليًا)
  • محاكي أو جهاز يعمل بنظام التشغيل Android (متاح من خلال "استوديو Android")
  • نموذج الرمز (يُرجى الاطّلاع على الخطوة التالية)

كيف تقيّم مستوى خبرتك في إنشاء التطبيقات المتوافقة مع 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"

  1. بعد انتهاء معالج الإعداد وظهور النافذة مرحبًا بك في استوديو Android، انقر على فتح مشروع حالي في Android Studio. انتقِل إلى الدليل الذي تم تثبيت نموذج الرمز عليه، واختَر java ->ضريح(أو ابحث في جهاز الكمبيوتر عن ضريح) لفتح مشروع الضريح.
  2. انتظر قليلاً حتى يُنشئ Android Studio المشروع ويزامنه، كما هو موضح من خلال مؤشرات الأنشطة أسفل نافذة Android Studio.
  3. في هذه المرحلة، قد يطرح Android Studio بعض أخطاء الإصدار لأنك تفتقد إلى حزمة تطوير البرامج (SDK) لنظام التشغيل Android أو أدوات الإصدار، مثل الأداة الموضّحة في ما يلي. اتبع التعليمات الواردة في "استوديو Android" لتثبيت هذه التطبيقات أو تعديلها ومزامنة مشروعك.

إضافة تبعيات المشاريع

يحتاج المشروع إلى اعتمادية على مكتبة دعم MDC Android. من المفترض أن يشتمل نموذج الرمز الذي تم تنزيله على هذه الاعتمادية من قبل، ولكن من الأفضل إجراء الخطوات التالية للتأكد من ذلك.

  1. انتقِل إلى ملف build.gradle في وحدة app وتأكَّد من أنّ كتلة dependencies تتضمن تبعية على MDC Android:
api 'com.google.android.material:material:1.1.0-alpha06'
  1. (اختياري) إذا لزم الأمر، عدِّل ملف 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'
}

تشغيل تطبيق إجراء التفعيل

  1. تأكَّد من أنّ بنية الإصدار على يمين زر التشغيل / التشغيل هي app.
  2. اضغط على الزر تشغيل / تشغيل الأخضر لإنشاء التطبيق وتشغيله.
  3. في نافذة اختيار هدف النشر، إذا كان لديك جهاز Android مُدرَج في الأجهزة المتاحة، يمكنك التخطّي إلى الخطوة 8. بخلاف ذلك، انقر على إنشاء جهاز افتراضي جديد.
  4. في شاشة اختيار الأجهزة، اختَر جهاز هاتف، مثل Pixel 2، ثم انقر على التالي.
  5. في شاشة System System (صورة النظام)، اختَر إصدار Android حديثًا، ويُفضَّل أن يكون أعلى مستوى لواجهة برمجة التطبيقات. وفي حال عدم تثبيت التطبيق، انقر على الرابط تنزيل الذي يظهر، ثم أكمِل عملية التنزيل.
  6. انقر على التالي.
  7. في شاشة جهاز Android الافتراضي (AVD)، اترك الإعدادات كما هي وانقر على إنهاء.
  8. اختَر جهاز Android من مربع حوار الهدف للنشر.
  9. انقر على حسنًا.
  10. ينشئ Android Studio التطبيق وينشره ويفتحه تلقائيًا على الجهاز المستهدف.

نجحت عملية تسجيل الدخول. من المفترض أن تظهر لك صفحة تسجيل الدخول في Shrine من الدرس التطبيقي حول الترميز MDC-101.

الآن وبعد ظهور شاشة تسجيل الدخول بشكل جيد، لنملأ التطبيق ببعض المنتجات.

يتم الكشف عن الشاشة الرئيسية عند إغلاق صفحة تسجيل الدخول، مع شاشة تعرض العبارة "لقد فعلت ذلك!" ذلك أمر رائع! ولكن الآن، لا يمكن للمستخدم اتخاذ أي إجراء أو أي مكان للمكان في التطبيق. وللمساعدة في ذلك، دعنا نضيف التنقل.

يوفر التصميم المتعدد الأبعاد أنماط تنقُّل تضمن درجة عالية من سهولة الاستخدام. يُعد شريط التطبيق العلوي من أهم مكونات التنقل.

لتوفير التنقل ومنح المستخدمين إمكانية الوصول السريع إلى الإجراءات الأخرى، دعنا نضيف شريط أهم التطبيقات.

إضافة أداة 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:

ProductNetworkFragment.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 في شريط الأدوات:

ProductNetworkFragment.java

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
   menuInflater.inflate(R.menu.shr_toolbar_menu, menu);
   super.onCreateOptionsMenu(menu, menuInflater);
}

والآن، عليك إضافة استدعاء إلى الطريقة setUpToolbar التي أضفناها إلى محتوى طريقة onCreateView() باستخدام ما يلي:

ProductNetworkFragment.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.

من المفترض أن تبدو الطريقة كالتالي:

ProductNetworkFragment.java

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

يحدّد الرمز أعلاه شريط التطبيقات من تنسيق XML ليكون شريط الإجراءات لهذا النشاط. تخبر معاودة الاتصال onCreateOptionsMenu النشاط المطلوب استخدامه كقائمتنا. في هذه الحالة، سيضع عناصر القائمة من R.menu.shr_toolbar_menu في شريط التطبيق.

يحتوي ملف القائمة على عنصرين: "Search" &"Filter".

shr_شريط_القائمة.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 على النحو التالي:

ProductNetworkFragment.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);
   }

}

إنشاء وتشغيل. من المفترض أن تظهر الشاشة الرئيسية على النحو التالي:

الآن يحتوي شريط الأدوات على رمز تنقل وعنوان ورمزين في الجانب الأيمن. يعرض شريط الأدوات أيضًا الارتفاع باستخدام ظل خفيف يُظهر طبقة مختلفة عن المحتوى.

الآن، بما أنّ التطبيق يحتوي على بنية منظّمة، لنبدأ تنظيم المحتوى من خلال وضعه في البطاقات.

إضافة بطاقة

لنبدأ بإضافة بطاقة واحدة أسفل شريط التطبيقات العلوي. يجب أن تحتوي البطاقة على منطقة لصورة وعنوان وتصنيف للنص الثانوي.

في 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>

إنشاء وتشغيل:

من خلال هذه المعاينة، يمكنك ملاحظة أنّ البطاقة مضمّنة من الحافة اليسرى للشاشة، وأنّ الزوايا دائرية الشكل وظلّ (يعبّر عن ارتفاع البطاقة). تُسمى المنطقة بأكملها باسم "container;" وبصرف النظر عن الحاوية نفسها، جميع العناصر داخلها اختيارية.

يمكنك إضافة العناصر التالية إلى الحاوية: نص العنوان والصورة المصغّرة أو الصورة الرمزية ونص العنوان الفرعي والتقسيمات وحتى الأزرار والرموز. على سبيل المثال، تحتوي البطاقة التي أنشأناها للتو على TextView (واحد للعنوان والعنوان الثانوي) في LinearLayout بمحاذاة عنوان البطاقة.

وتظهر البطاقات عادةً في مجموعة تتضمّن بطاقات أخرى. في القسم التالي من هذا الدرس التطبيقي حول الترميز، سنوضّحه كمجموعة في شبكة.

عند ظهور عدة بطاقات في شاشة، يتم تجميعها في مجموعة واحدة أو أكثر. البطاقات في الشبكة هي عبارة عن قيم متماثلة، ما يعني أنها تتشارك نفس مستوى الارتفاع أثناء الراحة (مثل ما لم يتم سحبها أو سحبها، ولكننا لن نغطي ذلك في هذا الدرس التطبيقي حول الترميز).

إعداد شبكة البطاقات

اطّلِع على ملف 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 نفسها.

ProductCardRecyclerViewAdaptiveer.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. يخزّن هذا الصف طرق العرض التي تؤثر على تنسيق البطاقة، حتى نتمكن من تعديلها لاحقًا.

ProductCardView Holder.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 الخاص بك:

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:

ProductNetworkFragment.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&#39، بالإضافة إلى إعداد محوّل RecyclerView&#39s وإعداده.

من المفترض أن يظهر ملف ProductGridFragment.java الآن على النحو التالي:

ProductNetworkFragment.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، أضِف طرق العرض الثلاث التالية:

ProductCardView Holder.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);
   }
}

في محول RecyclerViewViewHolder, عدّل طريقة onBindViewHolder() لضبط المعلومات في كل طريقة عرض:

ProductCardRecyclerViewAdaptiveer.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&#39s الذي يجب فعله بكل بطاقة باستخدام ViewHolder.

في هذه الحالة، يتم ضبط البيانات النصية في كل TextView وViewHolder، ويتم استدعاء ImageRequester للحصول على صورة من عنوان URL. ImageRequester هي فئة وفّرناها لك، وهي تستخدم مكتبة Volley (وهي موضوع خارج نطاق هذا الدرس التطبيقي حول الترميز، ولكن يمكنك استكشاف الرمز بنفسك).

إنشاء وتشغيل:

تظهر منتجاتنا الآن في التطبيق.

يتضمّن تطبيقنا تدفقًا أساسيًا ينقل المستخدم من شاشة تسجيل الدخول إلى شاشة رئيسية حيث يمكن عرض المنتجات. في بضعة أسطر من الرمز، أضفنا شريط تطبيق علوي يحتوي على عنوان وثلاثة أزرار، ومجموعة من البطاقات لتقديم محتوى التطبيق. أصبحت شاشتنا الرئيسية الآن عملية وبسيطة ذات بنية أساسية ومحتوى قابل للتنفيذ.

الخطوات التالية

باستخدام شريط التطبيق العلوي والبطاقة وحقل النص والزر، بدأنا الآن باستخدام أربعة مكونات أساسية لتصميم المواد الأساسية من مكتبة MDC-Android. يمكنك استكشاف المزيد من المكوّنات في مكوّنات MDC-Android للكتالوج في MDC Android.

على الرغم من أنّ هذه الميزة تعمل بشكل كامل، إلا أنّها لا تُظهر بعد أي علامة تجارية معيّنة. في MDC-103: Material Design المظهر باستخدام اللون والشكل والارتفاع والنوع، سنخصص نمط هذه المكونات للتعبير عن علامة تجارية عصرية نابضة بالحياة.

تمكّنتُ من إكمال هذا الدرس التطبيقي بقدرٍ معقول من الوقت والجهد.

أوافق بشدة أوافق محايد أعارض أعارض بشدة

أود مواصلة استخدام المكونات المتعددة في المستقبل

أوافق بشدة أوافق لستُ موافقًا أعارض أعارض بشدة