1. مقدمة
تساعد Material Components (MDC) المطوّرين في تنفيذ التصميم المتعدد الأبعاد. تم إنشاء MDC بواسطة فريق من المهندسين ومصممي تجربة المستخدم في Google، وتتضمّن عشرات المكوّنات الجميلة والوظيفية لواجهة المستخدم، وهي متاحة على Android وiOS والويب وFlutter.material.io/develop |
ما هي Material Design وMaterial Components لنظام التشغيل Android؟
التصميم المتعدد الأبعاد هو نظام لإنشاء منتجات رقمية جريئة وجميلة. من خلال توحيد الأسلوب والعلامة التجارية والتفاعل والحركة ضمن مجموعة متسقة من المبادئ والمكوّنات، يمكن لفِرق المنتجات تحقيق أكبر إمكانات التصميم.
بالنسبة إلى تطبيقات Android، تجمع مكوّنات Material لتطبيق Android (MDC Android) بين التصميم والهندسة من خلال مكتبة من المكوّنات لضمان الاتساق في تطبيقك. مع تطوّر نظام التصميم المتعدد الأبعاد، يتم تعديل هذه المكوّنات لضمان تنفيذها بشكل متّسق ودقيق والالتزام بمعايير تطوير الواجهة الأمامية في Google. تتوفّر MDC أيضًا على الويب وiOS وFlutter.
في هذا الدرس التطبيقي حول الترميز، ستنشئ صفحة تسجيل دخول باستخدام العديد من مكوّنات MDC Android.
ما ستنشئه
هذا الدرس التطبيقي حول الترميز هو الأول من بين 4 دروس تطبيقية حول الترميز ستساعدك في إنشاء تطبيق باسم Shrine، وهو تطبيق Android للتجارة الإلكترونية يبيع الملابس والسلع المنزلية. سيوضّح لك هذا التطبيق كيفية تخصيص المكوّنات لتعكس أي علامة تجارية أو تصميم باستخدام MDC-Android.
في هذا الدرس التطبيقي حول الترميز، ستنشئ صفحة تسجيل دخول إلى تطبيق Shrine تتضمّن ما يلي:
- حقلان نصيان، أحدهما لإدخال اسم المستخدم والآخر لكلمة المرور
- زرّان، أحدهما "إلغاء" والآخر "التالي"
- اسم التطبيق (Shrine)
- صورة شعار Shrine

مكوّنات MDC Android في هذا الدرس التطبيقي حول الترميز
- حقل نص
- زرّ
المتطلبات
- معرفة أساسية بتطوير تطبيقات Android
- استوديو Android (يمكنك تنزيله من هنا إذا لم يكن مثبّتًا لديك)
- محاكي Android أو جهاز Android (متاح من خلال استوديو Android)
- الرمز النموذجي (راجِع الخطوة التالية)
ما هو تقييمك لمستوى خبرتك في إنشاء تطبيقات Android؟
2. إعداد بيئة التطوير
بدء تشغيل "استوديو Android"
عند فتح استوديو Android، من المفترض أن تظهر نافذة بعنوان "مرحبًا بك في استوديو Android". ومع ذلك، إذا كانت هذه هي المرة الأولى التي تشغّل فيها "استوديو Android"، عليك اتّباع خطوات معالج إعداد "استوديو Android" باستخدام القيم التلقائية. قد تستغرق هذه الخطوة عدة دقائق لتنزيل الملفات اللازمة وتثبيتها، لذا يمكنك تركها تعمل في الخلفية أثناء تنفيذ القسم التالي.
تنزيل تطبيق الدرس التطبيقي للمبتدئين
يقع التطبيق التجريبي في الدليل material-components-android-codelabs-101-starter/java.
...أو استنسِخه من GitHub
لاستنساخ هذا الدرس التطبيقي حول الترميز من GitHub، شغِّل الأوامر التالية:
git clone https://github.com/material-components/material-components-android-codelabs cd material-components-android-codelabs/ git checkout 101-starter
تحميل رمز البداية في "استوديو Android"
- بعد انتهاء معالج الإعداد وظهور النافذة مرحبًا بك في "استوديو Android"، انقر على فتح مشروع حالي في "استوديو Android". انتقِل إلى الدليل الذي ثبّت فيه الرمز النموذجي، واختَر java -> shrine (أو ابحث عن shrine على جهاز الكمبيوتر) لفتح مشروع Shrine.
- انتظِر لحظة إلى أن ينتهي "استوديو Android" من إنشاء المشروع ومزامنته، كما هو موضّح من خلال مؤشرات النشاط في أسفل نافذة "استوديو Android".
- في هذه المرحلة، قد يعرض "استوديو Android" بعض أخطاء الإنشاء لأنّك لم تثبِّت حزمة تطوير البرامج (SDK) لنظام التشغيل Android أو أدوات الإنشاء، مثل تلك الموضّحة أدناه. اتّبِع التعليمات الواردة في "استوديو Android" لتثبيت/تعديل هذه الحزم ومزامنة مشروعك.
إضافة تبعيات المشروع
يجب أن يتضمّن المشروع اعتمادية لمكتبة دعم Android المتوافقة مع MDC. من المفترض أنّ الرمز النموذجي الذي نزّلته يتضمّن هذه الاعتمادية، ولكن من الأفضل اتّباع الخطوات التالية للتأكّد من ذلك.
- انتقِل إلى ملف
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 قيد التشغيل في المحاكي. يجب أن يظهر لك الاسم "Shrine" وشعار Shrine أسفله مباشرةً.

لنلقِ نظرة على التعليمات البرمجية. لقد وفّرنا إطار عمل بسيطًا للتنقّل Fragment في الرمز البرمجي النموذجي لعرض الأجزاء والتنقّل بينها.
افتح MainActivity.java في الدليل shrine -> app -> src -> main -> java -> com.google.codelabs.mdc.java.shrine. يجب أن يتضمّن ما يلي:
MainActivity.java
package com.google.codelabs.mdc.java.shrine;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;
public class MainActivity extends AppCompatActivity implements NavigationHost {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.shr_main_activity);
if (savedInstanceState == null) {
getSupportFragmentManager()
.beginTransaction()
.add(R.id.container, new LoginFragment())
.commit();
}
}
/**
* Navigate to the given fragment.
*
* @param fragment Fragment to navigate to.
* @param addToBackstack Whether or not the current fragment should be added to the backstack.
*/
@Override
public void navigateTo(Fragment fragment, boolean addToBackstack) {
FragmentTransaction transaction =
getSupportFragmentManager()
.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.java 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.java.
LoginFragment.java
package com.google.codelabs.mdc.java.shrine;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
/**
* Fragment representing the login screen for Shrine.
*/
public class LoginFragment extends Fragment {
@Override
public View onCreateView(
@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.shr_login_fragment, container, false);
// Snippet from "Navigate to the next Fragment" section goes here.
return view;
}
// "isPasswordValid" from "Navigate to the next Fragment" section method goes here
}
تعمل السمة 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" />
<!-- Snippet from "Add text fields" section goes here. -->
<!-- Snippet from "Add buttons" section goes here. -->
</LinearLayout>
</ScrollView>
في هذه الصورة، يمكننا رؤية <LinearLayout> مع <ImageView> في الأعلى، ما يمثّل شعار "المزار".
بعد ذلك، تظهر العلامة <TextView> التي تمثّل التصنيف "SHRINE". نص هذا التصنيف هو مصدر السلاسل النصية باسم @string/shr_app_name. إذا ضغطت على Command + Click (أو Control + Click) على اسم مصدر السلاسل النصية، أو فتحت app -> res -> values -> strings.xml، يمكنك الاطّلاع على ملف strings.xml الذي يتم فيه تحديد مصادر السلاسل النصية. وعند إضافة المزيد من موارد السلاسل في المستقبل، سيتم تحديدها هنا. يجب أن يحتوي كل مورد في هذا الملف على البادئة shr_ للإشارة إلى أنّه جزء من تطبيق Shrine.
بعد أن تعرّفت على الرمز الأولي، لننفّذ مكوّننا الأول.
3- إضافة حقول نصية
للبدء، سنضيف حقلَي نص إلى صفحة تسجيل الدخول ليتمكّن المستخدمون من إدخال اسم المستخدم وكلمة المرور. سنستخدم مكوّن "حقل النص" في MDC، والذي يتضمّن وظائف مدمجة تعرض تصنيفًا عائمًا ورسائل خطأ.

إضافة ملف 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"
android:inputType="text"
android:maxLines="1" />
</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على "صحيح" في العنصر كلمة المرور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"
android:inputType="text"
android:maxLines="1" />
</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>
جرِّب الآن تشغيل التطبيق. من المفترض أن تظهر لك صفحة تحتوي على حقلَي نص "اسم المستخدم" و "كلمة المرور".
إليك طريقة عمل الصورة المتحركة للتصنيف العائم:

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

إضافة ملف 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>
هذا كل شيء! عند تشغيل التطبيق، ستظهر تموّجات الحبر عند النقر على كل زر.

5- الانتقال إلى Fragment التالي
أخيرًا، سنضيف بعض رموز Java البرمجية إلى LoginFragment.java لربط الزر "التالي" بجزء آخر. ستلاحظ أنّ كل مكوّن أضفناه إلى التصميم كان يتضمّن id. سنستخدم هذه ids للإشارة إلى المكوّنات في الرمز البرمجي وإضافة بعض عمليات التحقّق من الأخطاء والتنقّل.
لنضِف طريقة isPasswordValid منطقية خاصة في LoginFragment.java أسفل onCreateView()، مع منطق لتحديد ما إذا كانت كلمة المرور صالحة أم لا. لأغراض هذا العرض التوضيحي، سنتأكّد فقط من أنّ كلمة المرور تتألف من 8 أحرف على الأقل:
LoginFragment.java
/*
In reality, this will have more complex logic including, but not limited to, actual
authentication of the username and password.
*/
private boolean isPasswordValid(@Nullable Editable text) {
return text != null && text.length() >= 8;
}
بعد ذلك، أضِف متتبِّع نقرات إلى الزر "التالي" لضبط الخطأ وإزالته استنادًا إلى طريقة isPasswordValid() التي أنشأناها للتو. في onCreateView()، يجب وضع أداة معالجة النقرات هذه بين سطر أداة الإنشاء وسطر return view.
بعد ذلك، لنضِف أداة معالجة أحداث رئيسية إلى كلمة المرور TextInputEditText للاستماع إلى أحداث رئيسية من شأنها إزالة الخطأ. يجب أن يستخدم المتتبِّع أيضًا isPasswordValid() للتحقّق مما إذا كانت كلمة المرور صالحة أم لا. يمكنك إضافة هذا الرمز مباشرةً أسفل أداة معالجة النقرات في onCreateView().
يجب أن تبدو طريقة onCreateView() الآن على النحو التالي:
LoginFragment.java
@Override
public View onCreateView(
@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.shr_login_fragment, container, false);
final TextInputLayout passwordTextInput = view.findViewById(R.id.password_text_input);
final TextInputEditText passwordEditText = view.findViewById(R.id.password_edit_text);
MaterialButton nextButton = view.findViewById(R.id.next_button);
// Set an error if the password is less than 8 characters.
nextButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (!isPasswordValid(passwordEditText.getText())) {
passwordTextInput.setError(getString(R.string.shr_error_password));
} else {
passwordTextInput.setError(null); // Clear the error
}
}
});
// Clear the error once more than 8 characters are typed.
passwordEditText.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View view, int i, KeyEvent keyEvent) {
if (isPasswordValid(passwordEditText.getText())) {
passwordTextInput.setError(null); //Clear the error
}
return false;
}
});
return view;
}
يمكننا الآن الانتقال إلى جزء آخر. عدِّل OnClickListener في onCreateView() للانتقال إلى جزء آخر عند نجاح عملية التحقّق من الخطأ. يمكنك إجراء ذلك عن طريق إضافة السطر التالي للانتقال إلى ProductGridFragment إلى حالة else في متتبِّع النقرات:
LoginFragment.java
...
((NavigationHost) getActivity()).navigateTo(new ProductGridFragment(), false); // Navigate to the next Fragment
...
يجب أن يبدو معالج النقر الآن على النحو التالي:
LoginFragment.java
...
MaterialButton nextButton = view.findViewById(R.id.next_button);
// Set an error if the password is less than 8 characters.
nextButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (!isPasswordValid(passwordEditText.getText())) {
passwordTextInput.setError(getString(R.string.shr_error_password));
} else {
passwordTextInput.setError(null); // Clear the error
((NavigationHost) getActivity()).navigateTo(new ProductGridFragment(), false); // Navigate to the next Fragment
}
}
});
...
يستدعي سطر الرمز الجديد هذا الطريقة navigateTo() من MainActivity للانتقال إلى جزء جديد، وهو ProductGridFragment. هذه الصفحة فارغة حاليًا وستعمل عليها في الدورة التدريبية MDC-102.
الآن، أنشئ التطبيق. انقر على الزر "التالي".
أحسنت! ستكون هذه الشاشة نقطة البداية لدرس البرمجة التالي الذي ستعمل عليه في MDC-102.
6. تم
باستخدام ترميز XML الأساسي و30 سطرًا من لغة Java، ساعدتك مكتبة Material Components for Android في إنشاء صفحة تسجيل دخول جذابة تتوافق مع إرشادات التصميم المتعدد الأبعاد، كما أنّها تبدو وتعمل بشكل متسق على جميع الأجهزة.
الخطوات التالية
يُعدّ "حقل النص" و"الزر" من المكوّنات الأساسية في مكتبة MDC لنظام التشغيل Android، ولكن هناك العديد من المكوّنات الأخرى. يمكنك استكشاف بقية المكوّنات في MDC Android. يمكنك بدلاً من ذلك الانتقال إلى MDC 102: بنية وتصميم التصميم المتعدد الأبعاد للتعرّف على شريط التطبيق العلوي وطريقة عرض البطاقة وتصميم الشبكة. نشكرك على تجربة Material Components. نأمل أن يكون هذا الدرس التطبيقي حول الترميز قد نال إعجابك.