MotionLayout
הוא סוג פריסה שעוזר לנהל תנועה ואנימציה של ווידג'טים באפליקציה. MotionLayout
הוא תת-סוג של ConstraintLayout
ומבוסס על יכולות הפריסה העשירות שלו. כחלק מספריית ConstraintLayout
, MotionLayout
זמינה כספריית תמיכה.
MotionLayout
מגשר על הפער בין מעברי פריסה וטיפול בתנועות מורכבות, ומספק שילוב של פיצ'רים בין המסגרת של האנימציה של הנכס, TransitionManager
ו-CoordinatorLayout
.
בנוסף לתיאור המעברים בין הפריסות, MotionLayout
מאפשר ליצור אנימציה לכל מאפיין פריסה. בנוסף, היא תומכת במעברים שניתן יהיה לבצע. כלומר, אפשר להציג באופן מיידי כל נקודה במעבר על סמך תנאי כלשהו, כמו קלט מגע. MotionLayout
תומך גם בפריימים מרכזיים, שמאפשרים ליצור מעברים מותאמים אישית לצרכים שלכם.
MotionLayout
הוא הצהרתי לחלוטין, כלומר אפשר לתאר מעברים ב-XML, גם אם הם מורכבים יותר.
שיקולים לגבי עיצוב
MotionLayout
מיועד להעביר, לשנות את הגודל ולספק אנימציה לרכיבי ממשק המשתמש שבהם המשתמשים מבצעים פעולות, כמו לחצנים וסרגלי כותרות. אין להשתמש בתנועה באפליקציה כאפקט מיוחד מיותר. אפשר להשתמש בה כדי לעזור למשתמשים להבין מה האפליקציה עושה. למידע נוסף על עיצוב האפליקציה עם תנועה, עיינו בקטע הסבר על תנועה בעיצוב חדשני.
שנתחיל?
כדי להתחיל להשתמש ב-MotionLayout
בפרויקט, פועלים לפי השלבים הבאים.
-
מוסיפים את התלות ב-
ConstraintLayout
: כדי להשתמש ב-MotionLayout
בפרויקט, מוסיפים את התלות ב-ConstraintLayout
2.0 לקובץbuild.gradle
של האפליקציה. אם משתמשים ב-AndroidX, צריך להוסיף את התלות הבאה:מגניב
dependencies { implementation "androidx.constraintlayout:constraintlayout:2.2.0-beta01" // To use constraintlayout in compose implementation "androidx.constraintlayout:constraintlayout-compose:1.1.0-beta01" }
Kotlin
dependencies { implementation("androidx.constraintlayout:constraintlayout:2.2.0-beta01") // To use constraintlayout in compose implementation("androidx.constraintlayout:constraintlayout-compose:1.1.0-beta01") }
-
יוצרים קובץ
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>
-
Create a 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"
. אופקית, נקודות הקצה נמצאות בקצה השמאלי והימני של המסך.
להמחשה מפורטת יותר של הרכיבים השונים שנתמכים בסצנה תנועה, אפשר לעיין בדוגמאות של פריסות התנועה.
-
מאפיינים שהומרו לפוליגונים
בתוך קובץ של סצנה של תנועה, רכיבי ConstraintSet
יכולים להכיל מאפיינים נוספים שעברו אינטרפולציה במהלך המעבר. בנוסף למיקום ולגבולות, המאפיינים הבאים משתנים על ידי MotionLayout
:
alpha
visibility
elevation
rotation
,rotationX
rotationY
translationX
,translationY
translationZ
scaleX
,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:customIntegerValue
למספרים שלמיםmotion:customFloatValue
לערכים צפיםmotion:customStringValue
למחרוזותmotion:customDimension
למאפייניםmotion:customBoolean
עבור ערכים בוליאניים
כשמציינים מאפיין מותאם אישית, צריך להגדיר את ערכי נקודות הקצה גם באלמנט <ConstraintSet>
של ההתחלה וגם באלמנט <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"
אפשר לציין במפורש את התקדמות המעבר. אפשר להשתמש בכל ערך של נקודה צפה (floating-point) מ-0
(התחלת המעבר) ל-1
(סיום המעבר). app:currentState="reference"
מאפשר לצייןConstraintSet
ספציפי.app:motionDebug
מאפשרת להציג מידע נוסף על ניפוי הבאגים של התנועה. הערכים האפשריים הם"SHOW_PROGRESS"
,"SHOW_PATH"
או"SHOW_ALL"
.
מקורות מידע נוספים
מידע נוסף על MotionLayout
זמין במקורות המידע הבאים:
- Android מתקדם ב-Kotlin 03.2: אנימציה באמצעות MotionLayout
- דוגמאות ל-MotionLayout
- דוגמאות MotionLayout/ConstraintLayout ב-GitHub
- מבוא לפריסה בתנועה (חלק I)
- מבוא לפריסת תנועה (חלק II)
- מבוא ל-MotionLayout (חלק III)
- מבוא ל-MotionLayout (חלק IV)