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

1. مقدمة

logo_components_color_2x_web_96dp.png

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

ما هو التصميم المتعدد الأبعاد والمكوّنات المادية لنظام Android؟

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

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

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

ما الذي ستنشئه

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

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

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

4cb0c218948144b4.png

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

  • حقل نصي
  • زرّ

المتطلبات

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

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

حديث متوسط بارع

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

بدء استخدام "استوديو Android"

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

KzoYWC1S7Se7yL8igi1vXF_mbVxAdl2lg5kb7RODrsVpEng0G6U3NK1Qnn0faBBZd2u71yMXioy9tD-7fv3NXvVO4N3EtMMeWDTmqBMMl6egd9R5uXX0T_SKmahbmRor3wZZHX0ByA

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

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

اكتمال عملية النقل بنجاح يجب أن يكون رمز إجراء التفعيل لصفحة تسجيل الدخول إلى 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(),، تبدأ MainActivity.kt معاملة Fragment لعرض LoginFragment. في هذا الدرس التطبيقي حول الترميز، سنعمل على تعديل LoginFragment. ينفِّذ النشاط أيضًا طريقة navigateTo(Fragment)، محدّدة في NavigationHost، ما يسمح لأي جزء بالانتقال إلى جزء مختلف.

Command + النقر (أو 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 + النقر (أو 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- الانتقال إلى الجزء التالي

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

لنضيف طريقة 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، ساعدتك مكتبة Material Components لمكتبة Android في إنشاء صفحة تسجيل دخول جميلة تتوافق مع إرشادات Material Design، وكذلك مظهر وتتصرف بشكل متسق عبر جميع الأجهزة.

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

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

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

أوافق بشدة أوافق ليست دقيقة ولا غير دقيقة لا أوافق لا أوافق أبدًا

أود مواصلة استخدام Material Components في المستقبل

أوافق بشدة أوافق ليست دقيقة ولا غير دقيقة لا أوافق لا أوافق أبدًا