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

مكوّنات MDC Android في هذا الدرس التطبيقي حول الترميز
- حقل نص
- زرّ
المتطلبات
- معرفة أساسية بتطوير تطبيقات Android
- استوديو Android (يمكنك تنزيله من هنا إذا لم يكن مثبّتًا لديك)
- محاكي Android أو جهاز Android (متاح من خلال Android Studio)
- الرمز النموذجي (راجِع الخطوة التالية)
ما هو تقييمك لمستوى خبرتك في إنشاء تطبيقات Android؟
بدء تشغيل "استوديو Android"
عند فتح استوديو Android، من المفترض أن تظهر نافذة بعنوان "مرحبًا بك في استوديو Android". ومع ذلك، إذا كانت هذه هي المرة الأولى التي تشغّل فيها Android Studio، عليك اتّباع خطوات معالج إعداد Android Studio باستخدام القيم التلقائية. قد تستغرق هذه الخطوة عدة دقائق لتنزيل الملفات الضرورية وتثبيتها، لذا يمكنك تركها تعمل في الخلفية أثناء تنفيذ القسم التالي.
تنزيل تطبيق الدرس التطبيقي الأوّلي
يقع التطبيق الأولي في الدليل 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" لتثبيت هذه الحِزم أو تعديلها ومزامنة مشروعك.
إضافة تبعيات المشروع
يجب أن يتضمّن المشروع تبعية لمكتبة دعم 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 قيد التشغيل في المحاكي. يجب أن يظهر لك الاسم "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(),، حيث تبدأ معاملة MainActivity.java لعرض Fragment.LoginFragment 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.
بعد أن تعرّفت على الرمز الأولي، لننفّذ مكوّننا الأول.
للبدء، سنضيف حقلَي نص إلى صفحة تسجيل الدخول ليتمكّن المستخدمون من إدخال اسم المستخدم وكلمة المرور. سنستخدم مكوّن "حقل النص" في 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>جرِّب الآن تشغيل التطبيق. من المفترض أن تظهر لك صفحة تتضمّن حقلَين نصيَّين لـ "اسم المستخدم" و "كلمة المرور".
إليك طريقة عمل الصورة المتحركة للتصنيف العائم:

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

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

أخيرًا، سنضيف بعض رموز 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.
باستخدام ترميز XML الأساسي ونحو 30 سطرًا من Java، ساعدتك مكتبة "مكوّنات Material Design لنظام التشغيل Android" في إنشاء صفحة تسجيل دخول مميزة تتوافق مع إرشادات Material Design، كما أنّها تبدو وتعمل بشكل متسق على جميع الأجهزة.
الخطوات التالية
يُعدّ "حقل النص" و"الزر" من المكوّنات الأساسية في مكتبة MDC لنظام التشغيل Android، ولكن هناك العديد من المكوّنات الأخرى. يمكنك استكشاف بقية المكوّنات في "تصميم المواد" على Android. يمكنك بدلاً من ذلك الانتقال إلى MDC 102: بنية وتصميم Material Design للتعرّف على شريط التطبيق العلوي وطريقة عرض البطاقة وتصميم الشبكة. نشكرك على تجربة Material Components. نأمل أن يكون هذا الدرس التطبيقي حول الترميز قد نال إعجابك.