1. מבוא
Material Design היא מערכת ליצירת מוצרים דיגיטליים נועזים ומרהיבים. כשמשלבים סגנון, מיתוג, אינטראקציה ותנועה במערך עקבי של עקרונות ורכיבים, צוותי המוצרים יכולים לממש את פוטנציאל העיצוב הגדול ביותר.
Material Components (MDC) עוזר למפתחים להטמיע Material Design. MDC נוצר על ידי צוות של מהנדסים ומעצבי חוויית המשתמש ב-Google, שכולל עשרות רכיבים יפים ופונקציונליים של ממשק המשתמש. זמין ל-Android, ל-iOS, לאינטרנט ול-Flutter.material.io/develop |
מהי מערכת התנועה של Material ל-Android?
מערכת התנועה Material ל-Android היא קבוצה של דפוסי מעבר בספריית MDC-Android, שיכולים לעזור למשתמשים להבין את האפליקציה ולנווט בה, כפי שמתואר בהנחיות של Material Design.
ארבעת הדפוסים העיקריים של מעבר Material הם:
- טרנספורמציה של קונטיינר: מעבר בין רכיבי ממשק משתמש שכוללים קונטיינר; יוצרת חיבור גלוי בין שני רכיבים נפרדים בממשק המשתמש על ידי המרה חלקה של רכיב אחד לרכיב אחר.
- ציר משותף: מעברים בין רכיבי ממשק משתמש שיש להם קשר מרחבי או ניווטי; משתמשת בטרנספורמציה משותפת על ציר ה-x, ה-y או ה-z כדי לחזק את הקשר בין יסודות.
- עמעום: מעבר בין אלמנטים של ממשק משתמש שאין להם קשר חזק זה לזה; משתמשת באפקט הדרגתי ועמעום הדרגתי, עם קנה מידה של הרכיב הנכנס.
- עמעום: משמש לרכיבים בממשק המשתמש שנכנסים לגבולות המסך או יוצאים מהם.
ספריית MDC-Android מציעה סיווגי מעבר לדפוסים האלה, שמבוססים על ספריית המעבר של AndroidX (androidx.transition
) וגם על מסגרת המעבר של Android (android.transition
):
AndroidX
- זמין בחבילה של
com.google.android.material.transition
- תמיכה ברמת API 14 ומעלה
- תומך ב-Fragments וב-Views, אבל לא בפעילויות או ב-Windows
- מכיל תיקוני באגים ברקע והתנהגות עקבית ברמות ה-API
מסגרת
- זמין בחבילה של
com.google.android.material.transition.platform
- תמיכה ברמת API ברמה 21 ואילך
- תמיכה ב-Fragments, בתצוגות, בפעילויות וב-Windows
- תיקוני באגים שלא הועברו לאחור ויכול להיות שאופן הפעולה שלהם יהיה שונה ברמות ה-API
ב-Codelab הזה תשתמשו במעברי Material שמבוססים על ספריית AndroidX, כלומר אתם תתמקדו בעיקר ב-Fragments וב-Views.
מה תפַתחו
ה-Codelab הזה ידריך אותך במעברים לאפליקציית אימייל לדוגמה ל-Android שנקראת Reply, באמצעות Kotlin, כדי להדגים איך אפשר להשתמש במעברים מספריית MDC-Android כדי להתאים אישית את העיצוב והסגנון של האפליקציה.
הקוד ההתחלתי של אפליקציית 'תשובה' יסופק, ואתם תשלבו את המעברים הבאים ב-Material באפליקציה. את המעברים הבאים אפשר לראות בקובץ ה-GIF שהושלם על ידי Codelab:
- מעבר של Container Transform מרשימת כתובות האימייל לדף הפרטים של האימייל
- מעבר של Container Transform מ-FAB לכתיבת דף אימייל
- מעבר ציר ה-Z המשותף מסמל החיפוש לדף הצפייה בחיפוש
- מעבר עמעום בין דפי תיבות דואר
- מעבר Container Transform מצ'יפ של כתובת אימייל לתצוגת כרטיס
מה צריך להכין
- ידע בסיסי בפיתוח Android ו-Kotlin
- Android Studio (אפשר להוריד אותו כאן אם עדיין אין לך אותו)
- אמולטור או מכשיר של Android (האפשרות זמינה ב-Android Studio)
- הקוד לדוגמה (מידע נוסף מופיע בשלב הבא)
איזה דירוג מגיע לדעתך לרמת הניסיון שלך בפיתוח אפליקציות ל-Android?
2. הגדרת סביבת הפיתוח
הפעלת Android Studio
כשפותחים את Android Studio, אמור להופיע חלון עם הכותרת 'איזה יופי שבחרת ב-Android Studio'. עם זאת, אם זו הפעם הראשונה שאתם מפעילים את Android Studio, עליכם לבצע את השלבים באשף ההגדרה של Android Studio ולציין את ערכי ברירת המחדל. ייתכן שתהליך ההורדה וההתקנה של הקבצים הדרושים יימשך מספר דקות, לכן ניתן להשאיר את הקובץ פועל ברקע בזמן ביצוע הקטע הבא.
אפשרות 1: שכפול אפליקציית Codelab למתחילים מ-GitHub
כדי לשכפל את codelab הזה מ-GitHub, מריצים את הפקודות הבאות:
git clone https://github.com/material-components/material-components-android-motion-codelab.git cd material-components-android-motion-codelab
אפשרות 2: מורידים את קובץ ה-ZIP של אפליקציית Codelab למתחילים
האפליקציה לתחילת הפעולה נמצאת בספרייה material-components-android-motion-codelab-develop
.
טוענים את הקוד לתחילת הפעולה ב-Android Studio
- כשאשף ההגדרה יסתיים ובחלון ברוכים הבאים אל Android Studio, לוחצים על פתיחת פרויקט קיים של Android Studio.
- עוברים אל הספרייה שבה התקנתם את הקוד לדוגמה ובוחרים את הספרייה לדוגמה כדי לפתוח את הפרויקט.
- ממתינים רגע עד שמערכת Android Studio תסיים לבנות ולסנכרן את הפרויקט, כפי שמוצג באינדיקטורים של הפעילות בחלק התחתון של החלון של Android Studio.
- בשלב הזה, ייתכן שיוצגו ב-Android Studio חלק משגיאות ה-build כי ה-SDK של Android או כלי ה-build חסרים לכם, כמו זה שמוצג למטה. כדי להתקין או לעדכן אותם ולסנכרן את הפרויקט, פועלים לפי ההוראות ב-Android Studio. אם אתם עדיין נתקלים בבעיות, תוכלו להיעזר במדריך לעדכון הכלים ב-SDK Manager.
אימות יחסי התלות של פרויקטים
הפרויקט צריך להיות תלוי בספריית MDC-Android. הקוד לדוגמה שהורדתם כבר אמור לכלול את התלות הזאת, אבל בואו נבחן את ההגדרות כדי לוודא זאת.
עוברים לקובץ build.gradle
של המודול app
ומוודאים שהבלוק dependencies
כולל תלות ב-MDC-Android:
implementation 'com.google.android.material:material:1.2.0'
הפעלת אפליקציה לתחילת פעולה
- צריך לוודא שתצורת ה-build שמימין לאפשרות המכשיר היא
app
. - לוחצים על לחצן ההפעלה / ההפעלה כדי לבנות את האפליקציה ולהפעיל אותה.
- בחלון בחירת יעד פריסה, אם כבר יש לכם מכשיר Android שרשום ברשימת המכשירים הזמינים, מדלגים לשלב 8. אחרת, לוחצים על יצירת מכשיר וירטואלי חדש.
- במסך בחירת חומרה, בוחרים מכשיר טלפון, למשל Pixel 3, ולוחצים על הבא.
- במסך תמונת המערכת, בוחרים גרסת Android האחרונה, רצוי רמת ה-API הגבוהה ביותר. אם היא לא מותקנת, לוחצים על הקישור הורדה שמופיע ומשלימים את ההורדה.
- לוחצים על הבא.
- במסך מכשיר וירטואלי של Android (AVD), משאירים את ההגדרות כפי שהן ולוחצים על סיום.
- בוחרים מכשיר Android מתיבת הדו-שיח של יעד הפריסה.
- לוחצים על אישור.
- מערכת Android Studio יוצרת את האפליקציה, פורסת אותה ופותח אותה באופן אוטומטי במכשיר היעד.
הצלחת! קוד הסימן לתחילת הפעולה בדף הבית של התשובה צריך לפעול באמולטור שלכם. תיבת הדואר הנכנס אמורה להכיל רשימה של כתובות אימייל.
אופציונלי: האטה של האנימציות במכשיר
מאחר שה-Codelab הזה כולל מעברים מהירים אך מלוטשים, כדאי להאט את האנימציות במכשיר כדי לצפות בחלק מהפרטים המדויקים יותר של המעברים בזמן ההטמעה. ניתן לעשות זאת באמצעות פקודות מעטפת של adb
או לחצן הגדרות מהירות. שימו לב שהשיטות האלה להאטת האנימציות במכשיר ישפיעו גם על האנימציות במכשיר מחוץ לאפליקציית 'תשובה'.
שיטה 1: פקודות ADB Shell
כדי להאט את האנימציות במכשיר פי 10, אפשר להריץ את הפקודות הבאות משורת הפקודה:
adb shell settings put global window_animation_scale 10
adb shell settings put global transition_animation_scale 10
adb shell settings put global animator_duration_scale 10
כדי לאפס את מהירות האנימציה במכשיר בחזרה למצב רגיל, מריצים את הפקודות הבאות:
adb shell settings put global window_animation_scale 1
adb shell settings put global transition_animation_scale 1
adb shell settings put global animator_duration_scale 1
שיטה 2: לחצן 'הגדרות מהירות'
לחלופין, כדי להגדיר את לחצן ההגדרות המהירות, קודם צריך להפעיל את ההגדרה למפתחים במכשיר אם עדיין לא עשית זאת:
- פתיחת המכשיר 'הגדרות' יישום
- גוללים למטה לחלק התחתון ולוחצים על 'מידע על מכשיר האמולציה'
- גוללים למטה ולוחצים במהירות על 'מספר Build'. עד להפעלת הגדרות המפתח
לאחר מכן, צריך לבצע את הפעולות הבאות, עדיין בתוך ה'הגדרות' של המכשיר , כדי להפעיל את לחצן ההגדרות המהירות:
- לוחצים על סמל החיפוש או על סרגל החיפוש בחלק העליון של המסך.
- מקלידים 'אריחים'. בשדה החיפוש
- לוחצים על 'כרטיסי מידע למפתחים של הגדרות מהירות' שורה
- לוחצים על 'קנה המידה של אנימציית החלון' מתג
לסיום, במהלך ה-Codelab, מושכים כלפי מטה את לוח הודעות המערכת מהחלק העליון של המסך ומשתמשים בסמל כדי להחליף בין אנימציות במהירות רגילה לאנימציות במהירות רגילה.
3. היכרות עם קוד האפליקציה לדוגמה
בואו נסתכל על הקוד. סיפקנו אפליקציה שמשתמשת בספרייה רכיב ניווט של Jetpack כדי לנווט בין כמה מקטעים שונים, והכול בפעילות אחת, MainActivity:
- HomeFragment: הצגת רשימה של אימיילים
- EmailFragment: מציג הודעת אימייל מלאה אחת
- ComposeFragment: מאפשר ליצור הודעת אימייל חדשה
- SearchFragment: הצגת תצוגה של חיפוש
navigation_graph.xml
קודם כול, כדי להבין איך מוגדר תרשים הניווט של האפליקציה, אפשר לפתוח את navigation_graph.xml
בספרייה app -> src -> main -> res -> navigation
:
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/navigation_graph"
app:startDestination="@id/homeFragment">
<fragment
android:id="@+id/homeFragment"
android:name="com.materialstudies.reply.ui.home.HomeFragment"
android:label="HomeFragment">
<argument...>
<action
android:id="@+id/action_homeFragment_to_emailFragment"
app:destination="@id/emailFragment" />
</fragment>
<fragment
android:id="@+id/emailFragment"
android:name="com.materialstudies.reply.ui.email.EmailFragment"
android:label="EmailFragment">
<argument...>
</fragment>
<fragment
android:id="@+id/composeFragment"
android:name="com.materialstudies.reply.ui.compose.ComposeFragment"
android:label="ComposeFragment">
<argument...>
</fragment>
<fragment
android:id="@+id/searchFragment"
android:name="com.materialstudies.reply.ui.search.SearchFragment"
android:label="SearchFragment" />
<action
android:id="@+id/action_global_homeFragment"
app:destination="@+id/homeFragment"
app:launchSingleTop="true"
app:popUpTo="@+id/navigation_graph"
app:popUpToInclusive="true"/>
<action
android:id="@+id/action_global_composeFragment"
app:destination="@+id/composeFragment" />
<action
android:id="@+id/action_global_searchFragment"
app:destination="@+id/searchFragment" />
</navigation>
כדאי לשים לב איך נמצאים כל המקטעים שהוזכרו למעלה, כאשר מקטע ההשקה שמוגדר כברירת מחדל מוגדר ל-HomeFragment
דרך app:startDestination="@id/homeFragment"
. הגדרת ה-XML הזו של תרשים היעד של המקטע, יחד עם הפעולות, מיידעת את קוד הניווט של Kotlin שנוצר כשאתם תפגשו כשתחברו מעברים.
activity_main.xml
בשלב הבא, נבחן את הפריסה activity_main.xml
בספרייה app -> src -> main -> res -> layout
. ה-NavHostFragment
שמוגדר עם תרשים הניווט שלמעלה יוצג:
<fragment
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="@navigation/navigation_graph"/>
ה-NavHostFragment
הזה ממלא את המסך ומטפל בכל השינויים באפליקציה כשמתבצע ניווט במקטעים במסך מלא. השדה BottomAppBar
וה-FloatingActionButton
המעוגנים שלו, גם הם ב-activity_main.xml
, מוצבים מעל המקטע הנוכחי שמוצג על ידי NavHostFragment
, ולכן יוצגו או יוסתרו בהתאם ליעד המקטע באמצעות קוד האפליקציה לדוגמה שסופק.
בנוסף, BottomNavDrawerFragment
ב-activity_main.xml
היא חלונית הזזה תחתונה שמכילה תפריט לניווט בין תיבות האימייל השונות. התפריט הזה מוצג באופן מותנה בלחיצה על לחצן הלוגו BottomAppBar
'תשובה'.
MainActivity.kt
לסיום, כדי לראות דוגמה לפעולת ניווט שנעשה בה שימוש, אפשר לפתוח את MainActivity.kt
בספרייה app -> src -> main -> java -> com.materialstudies.reply.ui
. מאתרים את הפונקציה navigateToSearch()
, שאמורה להיראות כך:
private fun navigateToSearch() {
val directions = SearchFragmentDirections.actionGlobalSearchFragment()
findNavController(R.id.nav_host_fragment).navigate(directions)
}
כך אפשר לנווט לדף של תצוגת החיפוש, בלי מעבר מותאם אישית. במהלך ה-Codelab הזה, תעמקו בפעילות MainActivity ובארבעה מקטעים עיקריים כדי להגדיר מעברי Material שפועלים במקביל לפעולות הניווט השונות באפליקציה.
עכשיו, אחרי שקראתם את הקוד לתחילת העבודה, ניישם את המעבר הראשון.
4. הוספת מעבר של Container Transform מרשימת כתובות האימייל לדף הפרטים של האימייל
כדי להתחיל, צריך להוסיף מעבר כשלוחצים על הודעת אימייל. לשינוי הזה בניווט, דפוס הטרנספורמציה של הקונטיינר מתאים מאוד כי הוא מיועד למעברים בין רכיבי ממשק משתמש שמכילים קונטיינר. הדפוס הזה יוצר חיבור גלוי בין שני רכיבים בממשק המשתמש.
לפני שמוסיפים קוד, כדאי לנסות להפעיל את אפליקציית 'תשובה' וללחוץ על הודעת אימייל. היא אמורה לבצע דילוג פשוט, כך שהמסך יוחלף ללא מעבר:
כדי להתחיל, צריך להוסיף מאפיין transitionName
ב-MaterialCardView
ב-email_item_layout.xml
, כפי שמוצג בקטע הקוד הבא:
email_item_layout.xml
android:transitionName="@{@string/email_card_transition_name(email.id)}"
שם המעבר מקבל במשאב מחרוזת עם פרמטר. עליך להשתמש במזהה של כל אימייל כדי לוודא שכל transitionName
בEmailFragment
שלנו הוא ייחודי.
עכשיו, אחרי שמסיימים להגדיר את שם המעבר של הפריט ברשימת כתובות האימייל, נעשה את אותו הדבר גם בפריסת פרטי האימייל. ב-fragment_email.xml
, מגדירים את ה-transitionName
של MaterialCardView
למשאב המחרוזת הבא:
fragment_email.xml
android:transitionName="@string/email_card_detail_transition_name"
בקובץ HomeFragment.kt
, צריך להחליף את הקוד שבכתובת onEmailClicked
בקטע הקוד הבא כדי ליצור את המיפוי מתצוגת ההתחלה (פריט ברשימת האימיילים) ומתצוגת הסיום (מסך פרטי האימייל):
HomeFragment.kt
val emailCardDetailTransitionName = getString(R.string.email_card_detail_transition_name)
val extras = FragmentNavigatorExtras(cardView to emailCardDetailTransitionName)
val directions = HomeFragmentDirections.actionHomeFragmentToEmailFragment(email.id)
findNavController().navigate(directions, extras)
עכשיו, אחרי שמסיימים להגדיר את הצנרת, אפשר ליצור טרנספורמציה של קונטיינר. בשיטה EmailFragment
onCreate
, מגדירים את sharedElementEnterTransition
למופע חדש של MaterialContainerTransform
(ייבוא של גרסת com.google.android.material.transition
לעומת הגרסה com.google.android.material.transition.platform
) על ידי הוספת קטע הקוד הבא:
EmailFragment.kt
sharedElementEnterTransition = MaterialContainerTransform().apply {
drawingViewId = R.id.nav_host_fragment
duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
scrimColor = Color.TRANSPARENT
setAllContainerColors(requireContext().themeColor(R.attr.colorSurface))
}
עכשיו אפשר לנסות להפעיל מחדש את האפליקציה.
הדברים מתחילים להיראות מצוין! כשלוחצים על הודעת אימייל ברשימת כתובות האימייל, טרנספורמציה של מאגר אמורה להרחיב את הפריט ברשימה לדף פרטים במסך מלא. עם זאת, שים לב איך לחיצה על 'חזרה' לא מכווצת את הודעת האימייל בחזרה לרשימה. בנוסף, רשימת כתובות האימייל תיעלם מיד בתחילת המעבר, ותציג את הרקע של החלון האפור. כך שעדיין לא סיימנו.
כדי לתקן את המעבר להחזרה, צריך להוסיף את שתי השורות הבאות ל-method onViewCreated
ב-HomeFragment.kt
:
HomeFragment.kt
postponeEnterTransition()
view.doOnPreDraw { startPostponedEnterTransition() }
כדאי לנסות להפעיל מחדש את האפליקציה. הקשה על מקש 'הקודם' אחרי פתיחת הודעת אימייל תכווץ את ההודעה בחזרה לרשימה. איזה יופי! כדאי להמשיך לשפר את האנימציה.
הבעיה של להיעלם רשימת כתובות האימייל היא כאשר בעת ניווט ל-Fragment חדש באמצעות רכיב הניווט, ה-Fragment הנוכחי מוסר מיד ומוחלף ב-Fragment החדש והנכנס. כדי שרשימת כתובות האימייל תישאר גלויה גם אחרי שמחליפים אותה, אפשר להוסיף מעבר ליציאה אל HomeFragment
.
צריך להוסיף את קטע הקוד הבא לשיטה HomeFragment
onEmailClicked
כדי שרשימת כתובות האימייל תקטן ביציאה ובחזרה אליה:
HomeFragment.kt
exitTransition = MaterialElevationScale(false).apply {
duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
}
reenterTransition = MaterialElevationScale(true).apply {
duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
}
בשלב הבא, כדי להבטיח שהמעבר של MaterialElevationScale
יחול במסך הבית כולו, במקום על כל אחת מהתצוגות הנפרדות בהיררכיה, צריך לסמן את RecyclerView
ב-fragment_home.xml
כקבוצת מעבר.
fragment_home.xml
android:transitionGroup="true"
בשלב הזה, צריכה להיות לכם טרנספורמציה של קונטיינר שפועל באופן מלא. לחיצה על הודעת אימייל מרחיבה את הפריט לרשימה במסך פרטים, תוך ביטול רשימת כתובות האימייל. הקשה על מקש 'הקודם' מכווצת את מסך פרטי האימייל בחזרה לפריט ברשימה, תוך הגדלת קנה המידה ברשימת האימיילים.
5. הוספת מעבר של Container Transform מ-FAB לכתיבת דף אימייל
נמשיך בטרנספורמציה של קונטיינר ונוסיף מעבר מלחצן הפעולה הצפה ל-ComposeFragment
, ונרחיב את לחצן ה-FAB לאימייל חדש שהמשתמש יכתוב. קודם כול, מריצים מחדש את האפליקציה ולוחצים על FAB כדי לראות שאין מעבר כשמפעילים את מסך כתיבת האימייל.
אנחנו משתמשים באותה מחלקה, אבל הדרך שבה אנחנו מגדירים את המופע הזה תהיה שונה כי ה-FAB נמצא ב-MainActivity
וה-ComposeFragment
ממוקם בתוך המאגר של מארח הניווט MainActivity
.
ב-ComposeFragment.kt
, צריך להוסיף את קטע הקוד הבא לשיטה onViewCreated
, ולהקפיד לייבא את גרסת androidx.transition
של Slide
.
ComposeFragment.kt
enterTransition = MaterialContainerTransform().apply {
startView = requireActivity().findViewById(R.id.fab)
endView = emailCardView
duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
scrimColor = Color.TRANSPARENT
containerColor = requireContext().themeColor(R.attr.colorSurface)
startContainerColor = requireContext().themeColor(R.attr.colorSecondary)
endContainerColor = requireContext().themeColor(R.attr.colorSurface)
}
returnTransition = Slide().apply {
duration = resources.getInteger(R.integer.reply_motion_duration_medium).toLong()
addTarget(R.id.email_card_view)
}
בנוסף לפרמטרים ששימשו להגדרת הטרנספורמציה הקודמת של הקונטיינר, startView
ו-endView
מוגדרים כאן באופן ידני. במקום להשתמש במאפייני transitionName
כדי ליידע את מערכת המעבר של Android אילו תצוגות צריך לשנות, אפשר לציין אותן באופן ידני במקרה הצורך.
עכשיו מפעילים מחדש את האפליקציה. ה-FAB אמור להשתנות למסך הכתיבה (יש לעיין בקובץ ה-GIF בסוף השלב הזה).
בדומה לשלב הקודם, צריך להוסיף מעבר אל HomeFragment
כדי שהוא לא ייעלם אחרי שהוא יוסר והוחלף על ידי ComposeFragment
.
מעתיקים את קטע הקוד הבא ל-method navigateToCompose
ב-MainActivity
לפני הקריאה NavController
navigate
.
MainActivity.kt
currentNavigationFragment?.apply {
exitTransition = MaterialElevationScale(false).apply {
duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
}
reenterTransition = MaterialElevationScale(true).apply {
duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
}
}
זהו זה השלב הזה! אמור להיות מעבר מ-FAB למסך הכתיבה שנראה כך:
6. הוספת מעבר של ציר ה-Z המשותף מסמל החיפוש לדף תצוגת החיפוש
בשלב הזה, נוסיף מעבר מסמל החיפוש לתצוגת החיפוש במסך מלא. מאחר שאין מאגר תגים קבוע שמעורב בשינוי הניווט הזה, אנחנו יכולים להשתמש במעבר מציר ה-Z המשותף כדי לחזק את הקשר המרחבי בין שני המסכים ולציין שזזים רמה אחת למעלה בהיררכיית האפליקציה.
לפני שמוסיפים קוד נוסף, מנסים להפעיל את האפליקציה ולהקיש על סמל החיפוש בפינה השמאלית התחתונה של המסך. פעולה זו אמורה להציג את מסך תצוגת החיפוש ללא מעבר.
כדי להתחיל, צריך למצוא את ה-method navigateToSearch
ב-MainActivity
ולהוסיף את קטע הקוד הבא לפני הקריאה ל-method NavController
navigate
, כדי להגדיר יציאה מהמקטע הנוכחי ולהזין מחדש מעברים בציר ה-Z MaterialSharedAxis
.
MainActivity.kt
currentNavigationFragment?.apply {
exitTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true).apply {
duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
}
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false).apply {
duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
}
}
בשלב הבא צריך להוסיף את קטע הקוד הבא לשיטה onCreate
ב-SearchFragment
, שמגדירה מעברים מסוג Enter ומחזיר MaterialSharedAxis
.
SearchFragment.kt
enterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true).apply {
duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
}
returnTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false).apply {
duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
}
לסיום, כדי להבטיח שהמעבר של MaterialSharedAxis
יחול במסך החיפוש כולו, במקום על כל אחת מהתצוגות הנפרדות בהיררכיה, צריך לסמן את LinearLayout
ב-fragment_search.xml
כקבוצת מעבר.
fragment_search.xml
android:transitionGroup="true"
זהו! עכשיו אפשר לנסות להפעיל מחדש את האפליקציה ולהקיש על סמל החיפוש. מסך תצוגת הבית ותצוגת החיפוש אמורים להתעמעם ולהתקדם לאורך ציר ה-Z באופן עומק, וכך ליצור אפקט חלק בין שני המסכים.
7. הוספת מעבר עמעום בין דפי תיבות דואר
בשלב הזה נוסיף מעבר בין תיבות דואר שונות. מכיוון שאנחנו לא רוצים להדגיש קשר מרחבי או היררכי, נשתמש בהדגשה כדי לבצע פעולת החלפה פשוטה. בין רשימות של כתובות אימייל.
לפני שמוסיפים קוד נוסף, נסו להפעיל את האפליקציה, להקיש על הלוגו של 'תשובה' בסרגל האפליקציות התחתון ולעבור בין תיבות דואר. רשימת כתובות האימייל אמורה להשתנות ללא מעבר.
כדי להתחיל, צריך למצוא את השיטה navigateToHome
ב-MainActivity
ולהוסיף את קטע הקוד הבא לפני הקריאה לשיטת NavController
מסוג navigate
, כדי להגדיר מעבר MaterialFadeThrough
מהמקטע הנוכחי.
MainActivity.kt
currentNavigationFragment?.apply {
exitTransition = MaterialFadeThrough().apply {
duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
}
}
בשלב הבא, פותחים את HomeFragment
. בקובץ onCreate
, צריך להגדיר את enterTransition
של המקטע הזה כמופע חדש של MaterialFadeThrough
.
HomeFragment.kt
enterTransition = MaterialFadeThrough().apply {
duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()
}
מפעילים מחדש את האפליקציה. כשפותחים את חלונית ההזזה לניווט התחתונה ומחליפים תיבות דואר, הרשימה הנוכחית של הודעות האימייל אמורה להתעמעם ולהקטין את התצוגה בזמן שהרשימה החדשה נעלמת. איזה יופי!
8. הוספת מעבר של Container Transform מצ'יפ של כתובת אימייל לתצוגת כרטיס
בשלב הזה, תוסיפו מעבר שממיר צ'יפ לכרטיס קופץ. כאן נעשה שימוש בטרנספורמציה של קונטיינר כדי ליידע את המשתמש שהפעולה שבוצעה בחלון הקופץ תשפיע על הצ'יפ שממנו הגיע החלון הקופץ.
לפני הוספת קוד, יש להריץ את אפליקציית 'תשובה', ללחוץ על הודעת אימייל ואז על 'תשובה' FAB, ולאחר מכן נסה ללחוץ על צ'יפ איש הקשר של הנמען. הצ'יפ אמור להיעלם מיד, וכרטיס עם כתובות האימייל של אותו איש קשר אמור להופיע בתצוגה בלי אנימציות.
כדי לבצע את השלב הזה, צריך לעבוד ב-ComposeFragment
. הפריסה שכבר הוספת לפריסה ComposeFragment
היא צ'יפים של נמענים (גלויים כברירת מחדל) וכרטיס נמען (לא נראים כברירת מחדל). צ'יפ של נמען והכרטיס הזה הם שתי התצוגות שנוצרות ביניהן טרנספורמציה של קונטיינר.
כדי להתחיל, פותחים את ComposeFragment
ומוצאים את השיטה expandChip
. מתבצעת קריאה לשיטה הזו כשלוחצים על ה-chip
שצוין. צריך להוסיף את קטע הקוד הבא מעל לשורות שמחליפה את הגדרת החשיפה recipientCardView
ו-chip
. הפעולה הזו תפעיל את הטרנספורמציה של מאגר התגים שרשום דרך beginDelayedTransition
.
ComposeFragment.kt
val transform = MaterialContainerTransform().apply {
startView = chip
endView = binding.recipientCardView
scrimColor = Color.TRANSPARENT
endElevation = requireContext().resources.getDimension(
R.dimen.email_recipient_card_popup_elevation_compat
)
addTarget(binding.recipientCardView)
}
TransitionManager.beginDelayedTransition(binding.composeConstraintLayout, transform)
אם האפליקציה מופעלת עכשיו, הצ'יפ אמור להפוך לכרטיס של כתובות אימייל עבור הנמען. בשלב הבא נגדיר את המעבר להחזרה כדי לכווץ את הכרטיס חזרה לצ'יפ.
בשיטה collapseChip
ב-ComposeFragment
, מוסיפים את קטע הקוד הבא כדי לכווץ את הכרטיס חזרה לצ'יפ.
ComposeFragment.kt
val transform = MaterialContainerTransform().apply {
startView = binding.recipientCardView
endView = chip
scrimColor = Color.TRANSPARENT
startElevation = requireContext().resources.getDimension(
R.dimen.email_recipient_card_popup_elevation_compat
)
addTarget(chip)
}
TransitionManager.beginDelayedTransition(binding.composeConstraintLayout, transform)
מפעילים מחדש את האפליקציה. לחיצה על הצ'יפ אמורה להרחיב את הצ'יפ לכרטיס בזמן שלוחצים עליו, ואז לכווץ את הכרטיס בחזרה לצ'יפ. איזה יופי!
9. הפעולה הושלמה
ספריית MDC-Android מתבססת על פחות מ-100 שורות של קוד Kotlin ועל מספר תגי עיצוב בסיסיים של XML, ובעזרתה ניתן ליצור מעברים יפים באפליקציה קיימת שעומדת בהנחיות של Material Design, וגם מראה ומתנהג באופן עקבי בכל מכשירי Android.
השלבים הבאים
למידע נוסף על מערכת התנועה Material, כדאי לעיין במפרט ובתיעוד המלא למפתחים, ולנסות להוסיף מעברי Material לאפליקציה!
תודה שניסית תנועה בעיצוב חדשני. אנחנו מקווים שנהניתם מה-Codelab הזה!