1. مقدمة
تساعد المكونات المادية (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)
- صورة لشعار الضريح
مكونات MDC Android في هذا الدرس التطبيقي حول الترميز
- حقل النص
- زرّ
المتطلبات
- معرفة أساسية بتطوير تطبيقات Android
- استوديو Android (يمكنك تنزيله من هنا إذا لم يكن متوفّرًا لديك)
- محاكي أو جهاز Android (متاح من خلال "استوديو Android")
- نموذج الرمز (انظر الخطوة التالية)
ما هو تقييمك لمستوى خبرتك في إنشاء تطبيقات Android؟
2. إعداد بيئة التطوير
بدء استخدام "استوديو Android"
عند فتح تطبيق Android Studio، من المفترض أن تظهر نافذة بعنوان "مرحبًا بك في Android Studio". ومع ذلك، إذا كانت هذه هي المرة الأولى التي تشغِّل فيها "استوديو 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 -> ضريح (أو ابحث في جهاز الكمبيوتر عن ضريح) لفتح مشروع الضريح.
- انتظِر قليلاً حتى ينشئ "استوديو 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" وشعار الضريح أسفله مباشرة.
لنلقِ نظرة على الرمز. لقد قدّمنا إطار عمل بسيطًا للتنقّل في 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 + النقر (أو 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>
تمثّل "الضريح". التصنيف. نص هذا التصنيف هو مورد سلسلة باسم @string/shr_app_name
. إذا استخدمت Command + النقر (أو 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- الانتقال إلى الجزء التالي
أخيرًا، سنضيف بعض رموز Java إلى LoginFragment.java
لربط العنصر "NEXT" زر إلى جزء آخر. ستلاحظ أنّ كل مكوّن من المكونات التي أضفناها إلى التنسيق تم تخصيص id
له. سنستخدم id
هذه للإشارة إلى المكوّنات في الرمز وإضافة بعض عمليات التحقّق من الأخطاء والتنقل.
لنضيف طريقة 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 لمكتبة Android في إنشاء صفحة تسجيل دخول جميلة تتوافق مع إرشادات التصميم المتعدد الأبعاد، وكذلك تبدو وتعمل بشكل متسق عبر جميع الأجهزة.
الخطوات التالية
يعد الحقل النصي والزر مكونين أساسيين في مكتبة MDC لنظام التشغيل Android، ولكن هناك المزيد! يمكنك الاطّلاع على باقي المكوّنات في تطبيق MDC Android. يمكنك بدلاً من ذلك الانتقال إلى MDC 102: بنية التصميم المتعدد الأبعاد والتنسيق للتعرّف على شريط التطبيق العلوي وعرض البطاقة وتنسيق الشبكة. شكرًا لتجربة Material Components. نأمل أن تكون قد استفدت من هذا الدرس التطبيقي حول الترميز.