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>
-
יצירת 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
:
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"
מאפשר לציין באופן מפורש את התקדמות המעבר. אפשר להשתמש בכל ערך של נקודה צפה מ-0
(תחילת המעבר) עד1
(סוף המעבר).app:currentState="reference"
מאפשר לצייןConstraintSet
ספציפי.app:motionDebug
מאפשרת להציג מידע נוסף על ניפוי הבאגים של התנועה. הערכים האפשריים הם"SHOW_PROGRESS"
,"SHOW_PATH"
או"SHOW_ALL"
.
מקורות מידע נוספים
מידע נוסף על MotionLayout
זמין במקורות המידע הבאים:
- Android מתקדם ב-Kotlin 03.2: אנימציה באמצעות MotionLayout
- דוגמאות ל-MotionLayout
- דוגמאות ל-MotionLayout/ConstraintLayout ב-GitHub
- מבוא ל-MotionLayout (חלק ראשון)
- מבוא ל-MotionLayout (חלק II)
- מבוא ל-MotionLayout (חלק III)
- מבוא ל-MotionLayout (חלק IV)