MotionLayout
הוא סוג פריסה שעוזר לכם לנהל את התנועה ואת האנימציה של הווידג'טים באפליקציה.
MotionLayout הוא מחלקת משנה של
ConstraintLayout ומבוסס על יכולות הפריסה העשירות שלה. MotionLayout
זמין כספריית תמיכה כחלק מהספרייה ConstraintLayout.
MotionLayout מגשר בין מעברים בפריסה לבין טיפול בתנועה מורכבת, ומציע שילוב של תכונות בין מסגרת האנימציה של המאפיינים, TransitionManager ו-CoordinatorLayout.
בנוסף לתיאור המעברים בין פריסות, MotionLayout מאפשרת להנפיש כל מאפיין פריסה. בנוסף, הוא תומך באופן מובנה במעברים שאפשר לדלג עליהם. כלומר, אתם יכולים להציג באופן מיידי כל נקודה במעבר על סמך תנאי מסוים, כמו קלט מגע. MotionLayout תומך גם ב-keyframes, שמאפשרים ליצור מעברים בהתאמה אישית מלאה לפי הצרכים שלכם.
MotionLayout הוא דקלרטיבי לחלוטין, כלומר אפשר לתאר כל מעבר ב-XML, לא משנה כמה הוא מורכב.
שיקולים לגבי העיצוב
MotionLayout נועד להזיז, לשנות גודל ולהנפיש רכיבי ממשק משתמש שהמשתמשים מקיימים איתם אינטראקציה, כמו כפתורים וסרגלי כותרת. אל תשתמשו בתנועה באפליקציה כאפקט מיוחד ללא סיבה. התיאור עוזר למשתמשים להבין מה האפליקציה עושה. מידע נוסף על עיצוב האפליקציה עם אנימציה זמין בקטע הסבר על אנימציה במאמר בנושא Material Design.
שנתחיל?
כדי להתחיל להשתמש ב-MotionLayout בפרויקט, פועלים לפי השלבים הבאים.
-
מוסיפים את התלות ב-
ConstraintLayout: כדי להשתמש ב-MotionLayoutבפרויקט, מוסיפים את התלות ב-ConstraintLayoutגרסה 2.0 לקובץbuild.gradleשל האפליקציה. אם אתם משתמשים ב-AndroidX, מוסיפים את יחסי התלות הבאים:מגניב
dependencies { implementation "androidx.constraintlayout:constraintlayout:2.2.1" // To use constraintlayout in compose implementation "androidx.constraintlayout:constraintlayout-compose:1.1.1" }
Kotlin
dependencies { implementation("androidx.constraintlayout:constraintlayout:2.2.1") // To use constraintlayout in compose implementation("androidx.constraintlayout:constraintlayout-compose:1.1.1") }
-
יוצרים קובץ
MotionLayout:MotionLayoutהוא מחלקת משנה שלConstraintLayout, כך שאפשר להמיר כלConstraintLayoutקיים ל-MotionLayoutעל ידי החלפת שם המחלקה בקובץ משאבי הפריסה, כמו בדוגמאות הבאות:AndroidX
<!-- before: ConstraintLayout --> <androidx.constraintlayout.widget.ConstraintLayout .../> <!-- after: MotionLayout --> <androidx.constraintlayout.motion.widget.MotionLayout .../>
ספריית תמיכה
<!-- before: ConstraintLayout --> <android.support.constraint.ConstraintLayout .../> <!-- after: MotionLayout --> <android.support.constraint.motion.MotionLayout .../>
דוגמה מלאה לקובץ
MotionLayout, שבו מוגדר הפריסה שמוצגת באיור 1:AndroidX
<?xml version="1.0" encoding="utf-8"?> <!-- activity_main.xml --> <androidx.constraintlayout.motion.widget.MotionLayout 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:id="@+id/motionLayout" android:layout_width="match_parent" android:layout_height="match_parent" app:layoutDescription="@xml/scene_01" tools:showPaths="true"> <View android:id="@+id/button" android:layout_width="64dp" android:layout_height="64dp" android:background="@color/colorAccent" android:text="Button" /> </androidx.constraintlayout.motion.widget.MotionLayout>
ספריית תמיכה
<?xml version="1.0" encoding="utf-8"?> <!-- activity_main.xml --> <android.support.constraint.motion.MotionLayout 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:id="@+id/motionLayout" android:layout_width="match_parent" android:layout_height="match_parent" app:layoutDescription="@xml/scene_01" tools:showPaths="true"> <View android:id="@+id/button" android:layout_width="64dp" android:layout_height="64dp" android:background="@color/colorAccent" android:text="Button" /> </android.support.constraint.motion.MotionLayout>
-
יצירת MotionScene: בדוגמה הקודמת
MotionLayoutהמאפייןapp:layoutDescriptionמפנה אל סצנת תנועה. סצנת תנועה היא קובץ משאבים בפורמט XML. בתוך רכיב הבסיס<MotionScene>, סצנת תנועה מכילה את כל תיאורי התנועה של הפריסה המתאימה. כדי להפריד בין נתוני הפריסה לבין תיאורי התנועה, כל תגMotionLayoutמפנה לסצנת תנועה נפרדת. ההגדרות בסצנת התנועה מקבלות עדיפות על פני הגדרות דומות ב-MotionLayout.דוגמה לקובץ של סצנת תנועה שמתארת את התנועה האופקית הבסיסית באיור 1:
<?xml version="1.0" encoding="utf-8"?> <MotionScene xmlns:android="http://schemas.android.com/apk/res/android" xmlns:motion="http://schemas.android.com/apk/res-auto"> <Transition motion:constraintSetStart="@+id/start" motion:constraintSetEnd="@+id/end" motion:duration="1000"> <OnSwipe motion:touchAnchorId="@+id/button" motion:touchAnchorSide="right" motion:dragDirection="dragRight" /> </Transition> <ConstraintSet android:id="@+id/start"> <Constraint android:id="@+id/button" android:layout_width="64dp" android:layout_height="64dp" android:layout_marginStart="8dp" motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintStart_toStartOf="parent" motion:layout_constraintTop_toTopOf="parent" /> </ConstraintSet> <ConstraintSet android:id="@+id/end"> <Constraint android:id="@+id/button" android:layout_width="64dp" android:layout_height="64dp" android:layout_marginEnd="8dp" motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintEnd_toEndOf="parent" motion:layout_constraintTop_toTopOf="parent" /> </ConstraintSet> </MotionScene>
שימו לב לנקודות הבאות:
-
<Transition>מכיל את ההגדרה הבסיסית של התנועה.-
motion:constraintSetStartו-motion:constraintSetEndהם הפניות לנקודות הקצה של התנועה. נקודות הקצה האלה מוגדרות ברכיבי<ConstraintSet>בהמשך סצנת התנועה. -
motion:durationמציין את מספר אלפיות השנייה שנדרשות להשלמת התנועה.
-
-
<OnSwipe>מאפשר ליצור שליטה באמצעות מגע לתנועה.-
motion:touchAnchorIdמתייחס לתצוגה שהמשתמש יכול להחליק ולגרור. -
motion:touchAnchorSideאומר שהתצוגה נגררת מהצד הימני. -
motion:dragDirectionמתייחס להתקדמות כיוון הגרירה. לדוגמה,motion:dragDirection="dragRight"פירושו שההתקדמות גדלה ככל שגוררים את התצוגה ימינה.
-
-
<ConstraintSet>כאן מגדירים את האילוצים השונים שמתארים את התנועה. בדוגמה הזו, מוגדר<ConstraintSet>אחד לכל נקודת קצה של התנועה. נקודות הקצה האלה ממוקמות במרכז באופן אנכי באמצעותapp:layout_constraintTop_toTopOf="parent"ו-app:layout_constraintBottom_toBottomOf="parent". בצורה אופקית, נקודות הקצה נמצאות בצד ימין ובצד שמאל של המסך.
לעיון מפורט יותר ברכיבים השונים שסצנת תנועה תומכת בהם, אפשר לעיין בדוגמאות ל-MotionLayout.
-
מאפיינים שעברו אינטרפולציה
בתוך קובץ של סצנת תנועה, רכיבי ConstraintSet יכולים להכיל מאפיינים נוספים שעוברים אינטרפולציה במהלך המעבר. בנוסף למיקום ולגבולות, המאפיינים הבאים עוברים אינטרפולציה על ידי MotionLayout:
alphavisibilityelevationrotation,rotationX,rotationYtranslationX,translationY,translationZscaleX,scaleY
מאפיינים מותאמים אישית
בתוך רכיב <Constraint>, אפשר להשתמש ברכיב <CustomAttribute> כדי לציין מעבר למאפיינים שלא קשורים רק למיקום או למאפייני View.
<Constraint android:id="@+id/button" ...> <CustomAttribute motion:attributeName="backgroundColor" motion:customColorValue="#D81B60"/> </Constraint>
ל-<CustomAttribute> יש שני מאפיינים משלו:
- הפרמטר
motion:attributeNameהוא חובה והוא צריך להיות זהה לאובייקט עם שיטות getter ו-setter. הפונקציות getter ו-setter צריכות להתאים לתבנית ספציפית. לדוגמה, יש תמיכה ב-backgroundColorכי לתצוגה יש שיטות בסיסיות שלgetBackgroundColor()ו-setBackgroundColor(). - המאפיין השני שחובה לספק תלוי בסוג הערך. בוחרים מבין הסוגים הנתמכים הבאים:
motion:customColorValueלצבעים-
motion:customIntegerValuefor integers motion:customFloatValueלמספרים עשרונייםmotion:customStringValueלמחרוזותmotion:customDimensionלמאפייניםmotion:customBooleanלערכים בוליאניים
כשמציינים מאפיין מותאם אישית, צריך להגדיר ערכים של נקודות קצה גם באלמנטים <ConstraintSet> של ההתחלה וגם של הסיום.
שינוי צבע הרקע
בהמשך לדוגמה הקודמת, נניח שרוצים שצבעי התצוגה ישתנו כחלק מהתנועה שלה, כמו שמוצג באיור 2.
מוסיפים רכיב <CustomAttribute> לכל רכיב ConstraintSet, כמו שמוצג בקטע הקוד הבא:
<ConstraintSet android:id="@+id/start"> <Constraint android:id="@+id/button" android:layout_width="64dp" android:layout_height="64dp" android:layout_marginStart="8dp" motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintStart_toStartOf="parent" motion:layout_constraintTop_toTopOf="parent"> <CustomAttribute motion:attributeName="backgroundColor" motion:customColorValue="#D81B60" /> </Constraint> </ConstraintSet> <ConstraintSet android:id="@+id/end"> <Constraint android:id="@+id/button" android:layout_width="64dp" android:layout_height="64dp" android:layout_marginEnd="8dp" motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintEnd_toEndOf="parent" motion:layout_constraintTop_toTopOf="parent"> <CustomAttribute motion:attributeName="backgroundColor" motion:customColorValue="#9999FF" /> </Constraint> </ConstraintSet>
מאפיינים נוספים של MotionLayout
בנוסף למאפיינים בדוגמה הקודמת, ל-MotionLayout יש מאפיינים אחרים שאולי תרצו לציין:
-
app:applyMotionScene="boolean"מציין אם להחיל את סצנת התנועה. ערך ברירת המחדל של המאפיין הזה הואtrue. app:showPaths="boolean"מציין אם להציג את נתיבי התנועה בזמן שהתנועה פועלת. ערך ברירת המחדל של המאפיין הזה הואfalse.-
app:progress="float"מאפשר לציין במפורש את התקדמות המעבר. אפשר להשתמש בכל ערך של נקודה צפה מ-0(ההתחלה של המעבר) עד1(הסוף של המעבר). - אפשר להשתמש ב-
app:currentState="reference"כדי לצייןConstraintSetספציפי. -
app:motionDebugמאפשר להציג מידע נוסף על ניפוי הבאגים של התנועה. הערכים האפשריים הם"SHOW_PROGRESS","SHOW_PATH"או"SHOW_ALL".
מקורות מידע נוספים
מידע נוסף על MotionLayout זמין במקורות המידע הבאים:
- Advanced Android in Kotlin 03.2: אנימציה בעזרת MotionLayout
- דוגמאות ל-MotionLayout
- דוגמאות ל-MotionLayout/ConstraintLayout ב-GitHub
- מבוא ל-MotionLayout (חלק א')
- היכרות עם MotionLayout (חלק ב')
- מבוא ל-MotionLayout (חלק ג')
- מבוא ל-MotionLayout (חלק 4)