MDC-101 Android: أساسيات المكوّنات المادية (MDC) (Kotlin)

1. مقدمة

logo_components_color_2x_web_96dp.png

تساعد Material Components (MDC) المطوّرين في تنفيذ التصميم المتعدد الأبعاد. تم إنشاء MDC بواسطة فريق من المهندسين ومصممي تجربة المستخدم في Google، وتتضمّن عشرات المكوّنات الجميلة والوظيفية لواجهة المستخدم، وهي متاحة على Android وiOS والويب وFlutter.material.io/develop

ما هي Material Design وMaterial Components لنظام التشغيل Android؟

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

بالنسبة إلى تطبيقات Android، يجمع Material Components for Android (MDC Android) بين التصميم والهندسة من خلال مكتبة من المكوّنات لضمان المطابقة في تطبيقك. ومع تطوّر نظام التصميم المتعدد الأبعاد، يتم تحديث هذه المكوّنات لضمان التنفيذ المتسق والدقيق والالتزام بمعايير تطوير الواجهة الأمامية من Google. تتوفّر MDC أيضًا على الويب وiOS وFlutter.

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

ما ستنشئه

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

في هذا الدرس التطبيقي حول الترميز، ستنشئ صفحة تسجيل دخول إلى تطبيق Shrine تتضمّن ما يلي:

  • حقلان نصيان، أحدهما لإدخال اسم المستخدم والآخر لكلمة المرور
  • زرّان، أحدهما "إلغاء" والآخر "التالي"
  • اسم التطبيق (Shrine)
  • صورة شعار Shrine

4cb0c218948144b4.png

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

  • حقل نصي
  • زرّ

المتطلبات

  • معرفة أساسية بتطوير تطبيقات Android
  • استوديو Android (يمكنك تنزيله من هنا إذا لم يكن مثبّتًا لديك)
  • محاكي Android أو جهاز Android (متاح من خلال استوديو Android)
  • الرمز النموذجي (راجِع الخطوة التالية)

ما هو تقييمك لمستوى خبرتك في إنشاء تطبيقات Android؟

مبتدئ متوسط متقدّم

2. إعداد بيئة التطوير

بدء تشغيل "استوديو Android"

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

تنزيل تطبيق الدرس التطبيقي للمبتدئين

يقع التطبيق التجريبي في الدليل material-components-android-codelabs-101-starter/kotlin.

...أو استنسِخه من GitHub

لاستنساخ هذا الدرس التطبيقي حول الترميز من GitHub، شغِّل الأوامر التالية:

git clone https://github.com/material-components/material-components-android-codelabs
cd material-components-android-codelabs/
git checkout 101-starter

تحميل رمز البداية في "استوديو Android"

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

KzoYWC1S7Se7yL8igi1vXF_mbVxAdl2lg5kb7RODrsVpEng0G6U3NK1Qnn0faBBZd2u71yMXioy9tD-7fv3NXvVO4N3EtMMeWDTmqBMMl6egd9R5uXX0T_SKmahbmRor3wZZHX0ByA

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

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

  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. في شاشة صورة النظام، اختَر إصدارًا حديثًا من Android، ويُفضّل اختيار أعلى مستوى لواجهة برمجة التطبيقات. إذا لم يكن مثبّتًا، انقر على الرابط تنزيل الذي يظهر وأكمِل عملية التنزيل.
  6. انقر على التالي.
  7. في شاشة الجهاز الافتراضي المتوافق مع Android (AVD)، اترك الإعدادات كما هي وانقر على إنهاء.
  8. اختَر جهاز Android من مربّع حوار "هدف النشر".
  9. انقر على حسنًا.
  10. ينشئ استوديو Android التطبيق ويفعّله ويفتحه تلقائيًا على جهاز الاختبار.

اكتمال النقل بنجاح يجب أن يكون الرمز الأوّلي لصفحة تسجيل الدخول إلى Shrine قيد التشغيل في المحاكي. يجب أن يظهر لك الاسم "Shrine" وشعار Shrine أسفله مباشرةً.

e7ed014e84755811.png

لنلقِ نظرة على التعليمات البرمجية. لقد وفّرنا إطار عمل بسيطًا للتنقّل Fragment في الرمز البرمجي النموذجي لعرض الأجزاء والتنقّل بينها.

افتح MainActivity.kt في الدليل shrine -> app -> src -> main -> java -> com.google.codelabs.mdc.kotlin.shrine. يجب أن يتضمّن ما يلي:

MainActivity.kt

package com.google.codelabs.mdc.kotlin.shrine

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment

class MainActivity : AppCompatActivity(), NavigationHost {

   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       setContentView(R.layout.shr_main_activity)

       if (savedInstanceState == null) {
           supportFragmentManager
                   .beginTransaction()
                   .add(R.id.container, LoginFragment())
                   .commit()
       }
   }

   override fun navigateTo(fragment: Fragment, addToBackstack: Boolean) {
       val transaction = supportFragmentManager
               .beginTransaction()
               .replace(R.id.container, fragment)

       if (addToBackstack) {
           transaction.addToBackStack(null)
       }

       transaction.commit()
   }
}

يعرض هذا النشاط ملف التنسيق R.layout.shr_main_activity، الذي تم تحديده في shr_main_activity.xml.

يمكنك الاطّلاع على ذلك في onCreate(),، حيث تبدأ معاملة Fragment لعرض LoginFragment.MainActivity.kt في هذا الدرس العملي، سنعدّل LoginFragment. ينفّذ النشاط أيضًا طريقة navigateTo(Fragment)، محدّدة في NavigationHost، تتيح لأي جزء الانتقال إلى جزء مختلف.

Command + Click (أو Control + Click) shr_main_activity في ملف النشاط لفتح ملف التصميم، أو انتقِل إلى ملف التصميم في app -> res -> layout -> shr_main_activity.xml.

shr_main_activity.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   android:id="@+id/container"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   tools:context=".MainActivity"/>

نرى هنا <FrameLayout> بسيطًا يعمل كحاوية لأي أجزاء تعرضها الشاشة.

بعد ذلك، لنفتح LoginFragment.kt.

LoginFragment.kt

package com.google.codelabs.mdc.kotlin.shrine

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment

class LoginFragment : Fragment() {

   override fun onCreateView(
           inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
       // Inflate the layout for this fragment
       val view = inflater.inflate(R.layout.shr_login_fragment, container, false)

       return view
   }
}

تعمل السمة LoginFragment على توسيع ملف التنسيق shr_login_fragment وعرضه في onCreateView().

لنلقِ نظرة الآن على ملف shr_login_fragment.xml لتصميم الصفحة لمعرفة الشكل الذي ستظهر به صفحة تسجيل الدخول.

shr_login_fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<ScrollView 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"
   android:background="@color/loginPageBackgroundColor"
   tools:context=".LoginFragment">

   <LinearLayout
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:clipChildren="false"
       android:clipToPadding="false"
       android:orientation="vertical"
       android:padding="24dp"
       android:paddingTop="16dp">

       <ImageView
           android:layout_width="64dp"
           android:layout_height="64dp"
           android:layout_gravity="center_horizontal"
           android:layout_marginTop="48dp"
           android:layout_marginBottom="16dp"
           app:srcCompat="@drawable/shr_logo" />

       <TextView
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:layout_gravity="center_horizontal"
           android:layout_marginBottom="132dp"
           android:text="@string/shr_app_name"
           android:textAllCaps="true"
           android:textSize="16sp" />
   </LinearLayout>
</ScrollView>

في هذه الصورة، يمكننا رؤية <LinearLayout> مع <ImageView> في الأعلى، ما يمثّل شعار الضريح.

بعد ذلك، تظهر العلامة <TextView> التي تمثّل تصنيف "المزار" أسفل الشعار. نص هذا التصنيف هو مصدر السلاسل النصية باسم @string/shr_app_name. إذا ضغطت على Command + Click (أو Control + Click) على اسم مصدر السلاسل النصية، أو فتحت app -> res -> values -> strings.xml، يمكنك الاطّلاع على ملف strings.xml الذي يتم فيه تحديد مصادر السلاسل النصية. وعند إضافة المزيد من موارد السلاسل في المستقبل، سيتم تحديدها هنا. يجب أن يحتوي كل مورد في هذا الملف على البادئة shr_ للإشارة إلى أنّه جزء من تطبيق Shrine.

بعد أن تعرّفت على الرمز الأولي، لننفّذ مكوّننا الأول.

3- إضافة حقول نصية

للبدء، سنضيف حقلَي نص إلى صفحة تسجيل الدخول ليتمكّن المستخدمون من إدخال اسم المستخدم وكلمة المرور. سنستخدم مكوّن "حقل النص" في MDC، والذي يتضمّن وظائف مدمجة تعرض تصنيفًا عائمًا ورسائل خطأ.

d83c47fb4aed3a82.png

إضافة ملف XML

في shr_login_fragment.xml، أضِف عنصرَي TextInputLayout مع عنصر ثانوي TextInputEditText داخل <LinearLayout>، أسفل التصنيف "SHRINE" <TextView>:

shr_login_fragment.xml

<com.google.android.material.textfield.TextInputLayout
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:layout_margin="4dp"
   android:hint="@string/shr_hint_username">

   <com.google.android.material.textfield.TextInputEditText
       android:layout_width="match_parent"
       android:layout_height="wrap_content" />
</com.google.android.material.textfield.TextInputLayout>

<com.google.android.material.textfield.TextInputLayout
   android:id="@+id/password_text_input"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:layout_margin="4dp"
   android:hint="@string/shr_hint_password">

   <com.google.android.material.textfield.TextInputEditText
       android:id="@+id/password_edit_text"
       android:layout_width="match_parent"
       android:layout_height="wrap_content" />
</com.google.android.material.textfield.TextInputLayout>

تمثّل المقتطفات أعلاه حقلَين نصيَّين، يتألف كلّ منهما من عنصر <TextInputLayout> وعنصر <TextInputEditText> ثانوي. يتم تحديد نص التلميح لكل حقل نصي في السمة android:hint.

لقد أدرجنا مرجعَين جديدَين للسلسلة في حقل النص، وهما @string/shr_hint_username و@string/shr_hint_password. افتح strings.xml للاطّلاع على موارد السلسلة هذه.

strings.xml

<string name="shr_hint_username">Username</string>
<string name="shr_hint_password">Password</string>

إضافة عملية التحقّق من صحة البيانات المُدخَلة

توفّر مكوّنات TextInputLayout وظيفة مدمجة لتقديم ملاحظات حول الأخطاء.

لعرض ملاحظات حول الأخطاء، عليك إجراء التغييرات التالية على shr_login_fragment.xml:

  • اضبط السمة app:errorEnabled على true في العنصر كلمة المرور TextInputLayout. سيؤدي ذلك إلى إضافة مساحة إضافية لرسالة الخطأ أسفل حقل النص.
  • اضبط السمة android:inputType على "textPassword" في العنصر كلمة المرور TextInputEditText. سيؤدي ذلك إلى إخفاء النص الذي تم إدخاله في حقل كلمة المرور.

بعد إجراء هذه التغييرات، ستظهر حقول النص في shr_login_fragment.xml على النحو التالي:

shr_login_fragment.xml

<com.google.android.material.textfield.TextInputLayout
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:layout_margin="4dp"
   android:hint="@string/shr_hint_username">

   <com.google.android.material.textfield.TextInputEditText
       android:layout_width="match_parent"
       android:layout_height="wrap_content" />
</com.google.android.material.textfield.TextInputLayout>

<com.google.android.material.textfield.TextInputLayout
   android:id="@+id/password_text_input"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:layout_margin="4dp"
   android:hint="@string/shr_hint_password"
   app:errorEnabled="true">

   <com.google.android.material.textfield.TextInputEditText
       android:id="@+id/password_edit_text"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:inputType="textPassword" />
</com.google.android.material.textfield.TextInputLayout>

جرِّب الآن تشغيل التطبيق. من المفترض أن تظهر لك صفحة تحتوي على حقلَي نص "اسم المستخدم" و "كلمة المرور".

إليك طريقة عمل الصورة المتحركة للتصنيف العائم:

333184b615aed4f7.gif

4. إضافة أزرار

بعد ذلك، سنضيف زرَّين إلى صفحة تسجيل الدخول: "إلغاء" و"التالي". سنستخدم مكوّن "زر" في MDC، والذي يتضمّن تأثير التموج بالحبر المميز في التصميم المتعدد الأبعاد.

4cb0c218948144b4.png

إضافة ملف XML

في shr_login_fragment.xml، أضِف <RelativeLayout> إلى <LinearLayout>، أسفل عناصر TextInputLayout. بعد ذلك، أضِف عنصرَي <MaterialButton> إلى <RelativeLayout>.

يجب أن يظهر ملف XML الناتج على النحو التالي:

shr_login_fragment.xml

<RelativeLayout
   android:layout_width="match_parent"
   android:layout_height="wrap_content">

   <com.google.android.material.button.MaterialButton
       android:id="@+id/next_button"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_alignParentEnd="true"
       android:layout_alignParentRight="true"
       android:text="@string/shr_button_next" />

   <com.google.android.material.button.MaterialButton
       android:id="@+id/cancel_button"
       style="@style/Widget.MaterialComponents.Button.TextButton"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_marginEnd="12dp"
       android:layout_marginRight="12dp"
       android:layout_toStartOf="@id/next_button"
       android:layout_toLeftOf="@id/next_button"
       android:text="@string/shr_button_cancel" />

</RelativeLayout>

هذا كل شيء! عند تشغيل التطبيق، ستظهر تموّجات الحبر عند النقر على كل زر.

9dd162d65e4a92a2.gif

5- الانتقال إلى Fragment التالي

أخيرًا، سنضيف بعض تعليمات Kotlin البرمجية إلى LoginFragment.kt لربط الزر "التالي" بالانتقال إلى جزء آخر.

لنضِف طريقة isPasswordValid منطقية خاصة في LoginFragment.kt أسفل onCreateView()، مع منطق لتحديد ما إذا كانت كلمة المرور صالحة أم لا. لأغراض هذا العرض التوضيحي، سنتأكّد فقط من أنّ كلمة المرور تتألف من 8 أحرف على الأقل:

LoginFragment.kt

private fun isPasswordValid(text: Editable?): Boolean {
   return text != null && text.length >= 8
}

بعد ذلك، أضِف متتبِّع نقرات إلى الزر "التالي" لضبط الخطأ وإزالته استنادًا إلى طريقة isPasswordValid() التي أنشأناها للتو. في onCreateView()، يجب وضع أداة معالجة النقرات هذه بين سطر أداة الإنشاء وسطر return view.

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

يجب أن تبدو طريقة onCreateView() الآن على النحو التالي:

LoginFragment.kt

override fun onCreateView(
           inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
       // Inflate the layout for this fragment.
       val view = inflater.inflate(R.layout.shr_login_fragment, container, false)

       // Set an error if the password is less than 8 characters.
       view.next_button.setOnClickListener({
           if (!isPasswordValid(password_edit_text.text!!)) {
               password_text_input.error = getString(R.string.shr_error_password)
           } else {
               // Clear the error.
               password_text_input.error = null
           }
       })

       // Clear the error once more than 8 characters are typed.
       view.password_edit_text.setOnKeyListener({ _, _, _ ->
           if (isPasswordValid(password_edit_text.text!!)) {
               // Clear the error.
               password_text_input.error = null
           }
           false
       })

       return view
   }
}

يمكننا الآن الانتقال إلى جزء آخر. في onCreateView()، عدِّل OnClickListener للانتقال إلى جزء آخر عند نجاح عملية التحقّق من صحة البيانات. يجب أن يبدو رمز clickListener الآن على النحو التالي:

LoginFragment.kt

// Set an error if the password is less than 8 characters.
view.next_button.setOnClickListener({
   if (!isPasswordValid(password_edit_text.text!!)) {
       password_text_input.error = getString(R.string.shr_error_password)
   } else {
       // Clear the error.
       password_text_input.error = null
       // Navigate to the next Fragment.
       (activity as NavigationHost).navigateTo(ProductGridFragment(), false)
   }
})

أضفنا السطر (activity as NavigationHost).navigateTo(ProductGridFragment(), false) إلى حالة else في أداة معالجة النقرة. يستدعي هذا السطر الطريقة navigateTo() من MainActivity للانتقال إلى جزء جديد، وهو ProductGridFragment. هذه الصفحة فارغة حاليًا وستعمل عليها في الدورة التدريبية MDC-102.

الآن، أنشئ التطبيق. انقر على الزر "التالي".

أحسنت! ستكون هذه الشاشة نقطة البداية لدرس البرمجة التالي الذي ستعمل عليه في MDC-102.

6. تم

باستخدام ترميز XML الأساسي ونحو 30 سطرًا من لغة Kotlin، ساعدتك مكتبة "مكوّنات التصميم المتعدد الأبعاد لنظام التشغيل Android" في إنشاء صفحة تسجيل دخول رائعة تتوافق مع إرشادات التصميم المتعدد الأبعاد، كما أنّها تبدو وتعمل بشكل متسق على جميع الأجهزة.

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

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

تمكّنتُ من إكمال هذا الدرس التطبيقي حول الترميز خلال فترة زمنية معقولة وبجهد معقول

أوافق بشدة أوافق لا أوافق ولا أعارض لا أوافق لا أوافق أبدًا

أريد مواصلة استخدام "مكوّنات Material" في المستقبل

أوافق بشدة أوافق لا أوافق ولا أعارض لا أوافق لا أوافق أبدًا