1. מבוא
Material Components (MDC) עוזר למפתחים להטמיע Material Design. MDC נוצר על ידי צוות של מהנדסים ומעצבי חוויית המשתמש ב-Google, שכולל עשרות רכיבים יפים ופונקציונליים של ממשק המשתמש. זמין ל-Android, ל-iOS, לאינטרנט ול-Flutter.material.io/develop |
מהם Material Design ורכיבי Material ל-Android?
Material Design היא מערכת ליצירת מוצרים דיגיטליים נועזים ומרהיבים. כשמשלבים סגנון, מיתוג, אינטראקציה ותנועה במערך עקבי של עקרונות ורכיבים, צוותי המוצרים יכולים לממש את פוטנציאל העיצוב הגדול ביותר.
באפליקציות ל-Android, השילוב של Material Components for Android (MDC Android) משלב עיצוב והנדסה עם ספרייה של רכיבים ליצירת עקביות באפליקציות שלכם. ככל שמערכת Material Design מתפתחת, הרכיבים האלה מתעדכנים כדי להבטיח הטמעה מושלמת של פיקסלים ותאימות לתקני הפיתוח בממשק הקצה של Google. MDC זמין גם לאינטרנט, ל-iOS ול-Flutter.
ב-Codelab הזה תבנו דף התחברות באמצעות כמה מהרכיבים של MDC Android.
מה תפַתחו
ה-Codelab הזה הוא הראשון מתוך 4 מעבדי קוד שינחו אותך בתהליך היצירה של אפליקציה בשם Shrine, אפליקציה ל-Android למסחר אלקטרוני למכירת בגדים ומוצרים לבית. הוא ידגים איך אפשר להתאים אישית את הרכיבים כך שישקפו כל מותג או סגנון באמצעות MDC-Android.
ב-Codelab הזה בונים דף התחברות למקדש שמכיל:
- שני שדות טקסט, אחד להזנת שם משתמש והשני לסיסמה
- שני לחצנים, אחד ל'ביטול' והשני בשביל 'הבא'
- שם האפליקציה (Shrine)
- תמונת הלוגו של מקדש
רכיבי Android של MDC ב-Codelab הזה
- שדה טקסט
- לחצן
מה צריך להכין
- ידע בסיסי בפיתוח Android
- Android Studio (אפשר להוריד אותו כאן אם עדיין אין לך אותו)
- אמולטור או מכשיר של Android (האפשרות זמינה ב-Android Studio)
- הקוד לדוגמה (מידע נוסף מופיע בשלב הבא)
איזה דירוג מגיע לדעתך לרמת הניסיון שלך בפיתוח אפליקציות ל-Android?
2. הגדרת סביבת הפיתוח
הפעלת Android Studio
כשפותחים את Android Studio, אמור להופיע חלון עם הכותרת 'איזה יופי שבחרת ב-Android Studio'. עם זאת, אם זו הפעם הראשונה שאתם מפעילים את Android Studio, עליכם לבצע את השלבים באשף ההגדרה של Android Studio ולציין את ערכי ברירת המחדל. ייתכן שתהליך ההורדה וההתקנה של הקבצים הדרושים יימשך מספר דקות, לכן ניתן להשאיר את הקובץ פועל ברקע בזמן ביצוע הקטע הבא.
להורדת האפליקציה לתחילת פעולה של Codelab
האפליקציה לתחילת הפעולה נמצאת בספרייה material-components-android-codelabs-101-starter/java
.
...או לשכפל אותו מ-GitHub
כדי לשכפל את ה-Codelab הזה מ-GitHub, מריצים את הפקודות הבאות:
git clone https://github.com/material-components/material-components-android-codelabs cd material-components-android-codelabs/ git checkout 101-starter
טוענים את הקוד לתחילת הפעולה ב-Android Studio
- כשאשף ההגדרה יסתיים ובחלון ברוכים הבאים אל Android Studio, לוחצים על פתיחת פרויקט קיים של Android Studio. מנווטים לספרייה שבה התקנתם את הקוד לדוגמה, ובוחרים באפשרות Java ->. מקדש (או לחפש במחשב את מקדש) כדי לפתוח את פרויקט המקדש.
- ממתינים רגע עד שמערכת Android Studio תסיים לבנות ולסנכרן את הפרויקט, כפי שמוצג באינדיקטורים של הפעילות בחלק התחתון של החלון של Android Studio.
- בשלב הזה, ייתכן שיוצגו ב-Android Studio חלק משגיאות ה-build כי ה-SDK של Android או כלי ה-build חסרים לכם, כמו זה שמוצג למטה. כדי להתקין או לעדכן אותם ולסנכרן את הפרויקט, פועלים לפי ההוראות ב-Android Studio.
הוספת יחסי תלות של פרויקטים
הפרויקט צריך להיות תלוי בספריית התמיכה של 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.
זה מה שנשנה ב-Codelab הזה. הפעילות גם מטמיעה שיטה של navigateTo(Fragment)
, שמוגדרת ב-NavigationHost
, שמאפשרת לכל מקטע לנווט למקטע אחר.
Command + לחיצה (או Control + לחיצה) 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 + לחיצה (או על Control + לחיצה) על שם המשאב במחרוזת, או פותחים את app -> res -> values -> strings.xml
, אפשר לראות את הקובץ strings.xml
שבו הוגדרו משאבי מחרוזות. כשיתווספו בעתיד משאבי מחרוזות נוספים, הם יוגדרו כאן. לכל משאב בקובץ הזה צריכה להיות קידומת shr_
כדי לציין שהוא חלק מאפליקציית המקדש.
עכשיו, אחרי שקראתם את קוד ההתחלה, נטמיע את הרכיב הראשון.
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
כ-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"
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. הוספת לחצנים
בשלב הבא, נוסיף שני לחצנים לדף ההתחברות שלנו: "ביטול" ו-"Next". נשתמש ברכיב של לחצן 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;
}
בשלב הבא, מוסיפים אוזן קליקים ל"Next" שמגדיר ומנקה את השגיאה בהתאם לשיטת ה-isPasswordValid()
שיצרנו עכשיו. ב-onCreateView()
, יש למקם את אוזן הקליקים הזה בין קו המנפח לבין השורה return view
.
בשלב הבא נוסיף אוזן מפתח לסיסמה TextInputEditText
כדי להאזין לאירועים מרכזיים שיבטלו את השגיאה. המאזינים האלה צריכים גם להשתמש ב-isPasswordValid()
כדי לבדוק אם הסיסמה חוקית. אפשר להוסיף אותו ישירות מתחת ל-Click Listener ב-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
של ה-clicklist:
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.
עכשיו אפשר לפתח את האפליקציה. צריך ללחוץ על הלחצן 'הבא'.
הצלחת! המסך הזה יהיה נקודת ההתחלה של ה-Codelab הבא שלנו שבו תעבוד ב-MDC-102.
6. הפעולה הושלמה
באמצעות שימוש בתגי עיצוב בסיסיים של XML וב-30 שורות ב-Java, ספריית Material Components for Android עזרה לכם ליצור דף התחברות יפהפה שתואם להנחיות של Material Design, וגם נראה ומתנהג באופן עקבי בכל המכשירים.
השלבים הבאים
הלחצן ושדה הטקסט הם שני רכיבי ליבה בספריית Android של MDC, אבל יש עוד הרבה דברים אחרים. אתם יכולים לעיין בשאר הרכיבים ב-MDC Android. לחלופין, אפשר לעבור אל MDC 102: מבנה ופריסה בעיצוב חדשני (Material Design) כדי לקבל מידע על סרגל האפליקציות העליון, תצוגת הכרטיסים ופריסת הרשת. תודה שניסית את רכיבי Material. אנחנו מקווים שנהניתם מה-Codelab הזה!