تساعد Material Components (MDC) المطوّرين في تنفيذ Material Design. تم إنشاء MDC بواسطة فريق من المهندسين ومصممي تجربة المستخدم في Google، وتتضمّن عشرات المكوّنات الجميلة والوظيفية لواجهة المستخدم، وهي متاحة على Android وiOS والويب وFlutter. material.io/develop |
في الدرس التطبيقي حول الترميز MDC-101، استخدَمت مكوّنَين من "مكوّنات التصميم المتعدد الأبعاد" (MDC) لإنشاء صفحة تسجيل دخول: حقول نصية وأزرار مع تأثيرات تموّج الحبر. والآن، لنوسّع نطاق هذا الأساس من خلال إضافة عناصر التنقّل والبنية والبيانات.
ما ستنشئه
في هذا الدرس التطبيقي حول الترميز، ستنشئ شاشة رئيسية لتطبيق يُسمى Shrine، وهو تطبيق للتجارة الإلكترونية يبيع الملابس والسلع المنزلية. ستتضمّن هذه الرسالة ما يلي:
- شريط تطبيق علوي
- قائمة شبكية مليئة بالمنتجات
مكوّنات MDC-Android في هذا الدرس التطبيقي حول الترميز
- AppBarLayout
- MaterialCardView
المتطلبات
- معرفة أساسية بتطوير تطبيقات Android
- استوديو Android (يمكنك تنزيله من هنا إذا لم يكن مثبّتًا لديك)
- محاكي Android أو جهاز Android (متاح من خلال Android Studio)
- الرمز النموذجي (راجِع الخطوة التالية)
ما هو تقييمك لمستوى خبرتك في إنشاء تطبيقات Android؟
هل سبق لك المشاركة في دورة MDC-101؟
إذا أكملت MDC-101، من المفترض أن يكون الرمز البرمجي جاهزًا لهذا الدرس العملي. انتقِل إلى الخطوة 3: إضافة شريط تطبيق علوي.
هل تريد البدء من الصفر؟
تنزيل تطبيق الدرس التطبيقي الأوّلي
يقع تطبيق البداية في دليل material-components-android-codelabs-102-starter/kotlin
. احرص على cd
في هذا الدليل قبل البدء.
...أو استنسِخه من GitHub
لاستنساخ هذا الدرس التطبيقي العملي من GitHub، شغِّل الأوامر التالية:
git clone https://github.com/material-components/material-components-android-codelabs cd material-components-android-codelabs/ git checkout 102-starter
تحميل الرمز الأولي في "استوديو Android"
- بعد انتهاء معالج الإعداد وظهور النافذة مرحبًا بك في "استوديو Android"، انقر على فتح مشروع حالي في "استوديو Android". انتقِل إلى الدليل الذي ثبّت فيه نموذج الرمز، واختَر kotlin -> shrine (أو ابحث في جهاز الكمبيوتر عن shrine) لفتح مشروع Shipping.
- انتظِر لحظة إلى أن ينتهي "استوديو Android" من إنشاء المشروع ومزامنته، كما هو موضّح من خلال مؤشرات النشاط في أسفل نافذة "استوديو Android".
- في هذه المرحلة، قد يعرض "استوديو Android" بعض أخطاء الإنشاء لأنّك لم تثبِّت حزمة تطوير البرامج (SDK) لنظام التشغيل Android أو أدوات الإنشاء، مثل تلك الموضّحة أدناه. اتّبِع التعليمات في "استوديو Android" لتثبيت هذه الحِزم أو تعديلها ومزامنة مشروعك.
إضافة تبعيات المشروع
يجب أن يتضمّن المشروع تبعية لمكتبة دعم 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 من برنامج 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
، أضِف ما يلي إلى عنصر Toolbar
XML الذي أضفته للتو إلى التصميم:
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، تُعرف هذه الأزرار باسم أزرار الإجراءات. سنصمّم شريط التطبيق العلوي ونضيف أزرار الإجراءات إلى القائمة آليًا.
في الدالة onCreateView
الخاصة بـ ProductGridFragment.kt
، اضبط Toolbar
الخاص بـ activity
ليتم استخدامه كـ ActionBar
باستخدام setSupportActionBar
. يمكنك إجراء ذلك بعد إنشاء العرض باستخدام inflater
.
ProductGridFragment.kt
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment with the ProductGrid theme
val view = inflater.inflate(R.layout.shr_product_grid_fragment, container, false)
// Set up the toolbar.
(activity as AppCompatActivity).setSupportActionBar(view.app_bar)
return view;
}
بعد ذلك، مباشرةً أسفل الطريقة التي غيّرناها للتو لإعداد شريط الأدوات، لنلغِ onCreateOptionsMenu
لتعبئة محتويات shr_toolbar_menu.xml
في شريط الأدوات:
ProductGridFragment.kt
override fun onCreateOptionsMenu(menu: Menu, menuInflater: MenuInflater) {
menuInflater.inflate(R.menu.shr_toolbar_menu, menu)
super.onCreateOptionsMenu(menu, menuInflater)
}
أخيرًا، يمكنك إلغاء onCreate()
في ProductGridFragment.kt
، وبعد استدعاء super()
، استدعاء setHasOptionMenu
مع true
:
ProductGridFragment.kt
override fun onCreate(savedInstanceState: Bundle?) {
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.kt
على النحو التالي:
ProductGridFragment.kt
package com.google.codelabs.mdc.kotlin.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 androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.GridLayoutManager
import com.google.codelabs.mdc.kotlin.shrine.network.ProductEntry
import kotlinx.android.synthetic.main.shr_product_grid_fragment.view.*
class ProductGridFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment with the ProductGrid theme
val view = inflater.inflate(R.layout.shr_product_grid_fragment, container, false)
// Set up the tool bar
(activity as AppCompatActivity).setSupportActionBar(view.app_bar)
return view;
}
override fun 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>
إنشاء التطبيق وتشغيله:
في هذه المعاينة، يمكنك ملاحظة أنّ البطاقة مضمّنة من الحافة اليسرى، وأنّها تتضمّن زوايا مستديرة وظلاً (يعبّر عن ارتفاع البطاقة). يُطلق على العنصر بأكمله اسم "الحاوية". باستثناء الحاوية، تكون جميع العناصر داخلها اختيارية.
يمكنك إضافة العناصر التالية إلى الحاوية: نص العنوان، وصورة مصغّرة أو صورة رمزية، ونص العنوان الفرعي، والفواصل، وحتى الأزرار والأيقونات. على سبيل المثال، تحتوي البطاقة التي أنشأناها للتو على عنصرَي 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
.
ProductCardRecyclerViewAdapter.kt
package com.google.codelabs.mdc.kotlin.shrine
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.google.codelabs.mdc.kotlin.shrine.network.ProductEntry
/**
* Adapter used to show a simple grid of products.
*/
class ProductCardRecyclerViewAdapter(private val productList: List<ProductEntry>) : RecyclerView.Adapter<ProductCardViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProductCardViewHolder {
val layoutView = LayoutInflater.from(parent.context).inflate(R.layout.shr_product_card, parent, false)
return ProductCardViewHolder(layoutView)
}
override fun onBindViewHolder(holder: ProductCardViewHolder, position: Int) {
// TODO: Put ViewHolder binding code here in MDC-102
}
override fun getItemCount(): Int {
return productList.size
}
}
يدير فئة المحوّل أعلاه محتوى الشبكة. لتحديد ما يجب أن يفعله كل عرض بالمحتوى المقدَّم له، سنكتب قريبًا الرمز البرمجي الخاص بـ onBindViewHolder()
.
في الحزمة نفسها، يمكنك أيضًا إلقاء نظرة على ProductCardViewHolder
. يخزّن هذا الصف طرق العرض التي تؤثر في تصميم البطاقة، حتى نتمكّن من تعديلها لاحقًا.
package com.google.codelabs.mdc.kotlin.shrine
import android.view.View
import androidx.recyclerview.widget.RecyclerView
class ProductCardViewHolder(itemView: View) //TODO: Find and store views from itemView
: RecyclerView.ViewHolder(itemView)
لإعداد الشبكة، علينا أولاً إزالة العنصر النائب MaterialCardView
من shr_product_grid_fragment.xml
. بعد ذلك، عليك إضافة المكوّن الذي يمثّل شبكة البطاقات. في هذه الحالة، سنستخدم RecyclerView. أضِف مكوّن 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.kt
بعد استدعاء setUpToolbar(view)
وقبل عبارة return
:
ProductGridFragment.kt
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment with the ProductGrid theme
val view = inflater.inflate(R.layout.shr_product_grid_fragment, container, false)
// Set up the toolbar.
(activity as AppCompatActivity).setSupportActionBar(view.app_bar)
// Set up the RecyclerView
view.recycler_view.setHasFixedSize(true)
view.recycler_view.layoutManager = GridLayoutManager(context, 2, RecyclerView.VERTICAL, false)
val adapter = ProductCardRecyclerViewAdapter(
ProductEntry.initProductEntryList(resources))
view.recycler_view.adapter = adapter
val largePadding = resources.getDimensionPixelSize(R.dimen.shr_product_grid_spacing)
val smallPadding = resources.getDimensionPixelSize(R.dimen.shr_product_grid_spacing_small)
view.recycler_view.addItemDecoration(ProductGridItemDecoration(largePadding, smallPadding))
return view;
}
يحتوي مقتطف الرمز أعلاه على خطوات الإعداد اللازمة لضبط RecyclerView
. يشمل ذلك ضبط أداة إدارة التنسيق في RecyclerView
، بالإضافة إلى تهيئة أداة الربط في RecyclerView
وضبطها.
يجب أن يظهر ملف ProductGridFragment.kt
الآن على النحو التالي:
ProductGridFragment.kt
package com.google.codelabs.mdc.kotlin.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 androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.codelabs.mdc.kotlin.shrine.network.ProductEntry
import kotlinx.android.synthetic.main.shr_product_grid_fragment.view.*
class ProductGridFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment with the ProductGrid theme
val view = inflater.inflate(R.layout.shr_product_grid_fragment, container, false)
// Set up the toolbar.
(activity as AppCompatActivity).setSupportActionBar(view.app_bar)
// Set up the RecyclerView
view.recycler_view.setHasFixedSize(true)
view.recycler_view.layoutManager = GridLayoutManager(context, 2, RecyclerView.VERTICAL, false)
val adapter = ProductCardRecyclerViewAdapter(
ProductEntry.initProductEntryList(resources))
view.recycler_view.adapter = adapter
val largePadding = resources.getDimensionPixelSize(R.dimen.shr_product_grid_spacing)
val smallPadding = resources.getDimensionPixelSize(R.dimen.shr_product_grid_spacing_small)
view.recycler_view.addItemDecoration(ProductGridItemDecoration(largePadding, smallPadding))
return view;
}
override fun onCreateOptionsMenu(menu: Menu, menuInflater: MenuInflater) {
menuInflater.inflate(R.menu.shr_toolbar_menu, menu)
super.onCreateOptionsMenu(menu, menuInflater)
}
}
إنشاء التطبيق وتشغيله:
أصبحت البطاقات متوفّرة الآن. لا تعرض هذه السمة أي معلومات بعد، لذا لنضِف بعض بيانات المنتجات.
إضافة صور ونصوص
أضِف صورة واسم منتج وسعرًا لكل بطاقة. يحتوي تجريد ViewHolder
على عدد المشاهدات لكل بطاقة. في ViewHolder
، أضِف طرق العرض الثلاث على النحو التالي.
ProductCardViewHolder.kt
package com.google.codelabs.mdc.kotlin.shrine
import android.view.View
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.android.volley.toolbox.NetworkImageView
class ProductCardViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var productImage: NetworkImageView = itemView.findViewById(R.id.product_image)
var productTitle: TextView = itemView.findViewById(R.id.product_title)
var productPrice: TextView = itemView.findViewById(R.id.product_price)
}
عدِّل طريقة onBindViewHolder()
في ProductCardRecyclerViewAdapter
لضبط العنوان والسعر وصورة المنتج لكل عرض منتج كما هو موضّح أدناه:
ProductCardRecyclerViewAdapter.kt
override fun onBindViewHolder(holder: ProductCardViewHolder, position: Int) {
if (position < productList.size) {
val product = productList[position]
holder.productTitle.text = product.title
holder.productPrice.text = product.price
ImageRequester.setImageFromUrl(holder.productImage, product.url)
}
}
يخبر الرمز البرمجي أعلاه محوّل RecyclerView
بما يجب فعله بكل بطاقة، وذلك باستخدام ViewHolder
.
في هذا المثال، يتم ضبط البيانات النصية على كل ViewHolder
من TextView
، ويتم استدعاء ImageRequester
للحصول على صورة من عنوان URL. ImageRequester
هي فئة قدّمناها لتسهيل الأمر عليك، وهي تستخدم مكتبة Volley
(هذا موضوع خارج نطاق هذا الدرس العملي، ولكن يمكنك استكشاف الرمز البرمجي بنفسك).
إنشاء التطبيق وتشغيله:
تظهر منتجاتنا الآن في التطبيق.
يتضمّن تطبيقنا مسارًا أساسيًا ينقل المستخدم من شاشة تسجيل الدخول إلى الشاشة الرئيسية، حيث يمكن عرض المنتجات. من خلال بضعة أسطر من الرمز البرمجي، أضفنا شريط تطبيق علويًا يتضمّن عنوانًا وثلاثة أزرار، بالإضافة إلى شبكة من البطاقات لعرض محتوى تطبيقنا. أصبحت شاشتنا الرئيسية بسيطة وعملية، وتتضمّن بنية أساسية ومحتوى قابلاً للتنفيذ.
الخطوات التالية
باستخدام شريط التطبيق العلوي والبطاقة وحقل النص والزر، نكون قد استخدمنا الآن أربعة مكوّنات أساسية من Material Design من مكتبة MDC-Android. يمكنك استكشاف المزيد من المكوّنات من خلال الانتقال إلى "كتالوج MDC-Android".
على الرغم من أنّ تطبيقنا يعمل بكامل وظائفه، إلا أنّه لا يعرض أي علامة تجارية أو تصميم معيّنَين حتى الآن. في MDC-103: تصميم Material Design باستخدام اللون والشكل والارتفاع والنوع، سنخصّص نمط هذه المكوّنات للتعبير عن علامة تجارية عصرية وحيوية.