ניהול האנימציה של התנועה והווידג'ט בעזרת MotionLayout

MotionLayout הוא סוג פריסה שעוזר לנהל את התנועה והווידג'ט של האנימציה באפליקציה. MotionLayout הוא תת-מחלקה של ConstraintLayout ומתבסס על מגוון עשיר של יכולות פריסה. כחלק מספריית ConstraintLayout, MotionLayout זמין בתור ספריית תמיכה.

MotionLayout מגשר על הפער בין מעברי הפריסה ותנועה מורכבת לטיפול, ומציע שילוב של תכונות בין האנימציה של הנכס framework, TransitionManager, וגם CoordinatorLayout.

איור 1. תנועה בסיסית לשליטה במגע.

נוסף לתיאור המעברים בין הפריסות, MotionLayout מאפשר לך מוסיפים אנימציה לכל מאפייני הפריסה. בנוסף, הוא תומך מעצם טבעו מעברים בין חשבונות. כלומר, אתם יכולים להציג באופן מיידי כל נקודה במהלך המעבר בהתאם למצב מסוים, כמו קלט מגע. MotionLayout תומך גם ב- תמונות מפתח, שמאפשרים מעברים מותאמים אישית באופן מלא לפי הצרכים שלכם.

המונח MotionLayout הוא הצהרתי לחלוטין, כלומר אפשר לתאר כל מעבר XML, לא משנה עד כמה הוא מורכב.

שיקולים לגבי התכנון

MotionLayout מיועד להזיז, לשנות את הגודל ולהנפיש רכיבי ממשק משתמש של המשתמשים, למשל לחצנים וסרגלי כותרות. אין להשתמש בתנועה באפליקציה בתור אפקט מיוחד מיותר. אפשר להיעזר בה כדי לעזור למשתמשים להבין מהי האפליקציה לעשות. למידע נוסף על עיצוב האפליקציה עם תנועה, אפשר לעיין ב הקטע Material Design הבנה .

שנתחיל?

כדי להתחיל להשתמש ב-MotionLayout בפרויקט, צריך לבצע את השלבים הבאים.

  1. מוסיפים את התלות ConstraintLayout: כדי להשתמש בה MotionLayout בפרויקט, צריך להוסיף את ConstraintLayout 2.0 תלויה באפליקציה שלך קובץ build.gradle. אם משתמשים ב-AndroidX, צריך להוסיף את הקוד של התלות הזאת:

    מגניב

    dependencies {
        implementation "androidx.constraintlayout:constraintlayout:2.2.0-alpha14"
        // To use constraintlayout in compose
        implementation "androidx.constraintlayout:constraintlayout-compose:1.1.0-alpha14"
    }
    

    Kotlin

    dependencies {
        implementation("androidx.constraintlayout:constraintlayout:2.2.0-alpha14")
        // To use constraintlayout in compose
        implementation("androidx.constraintlayout:constraintlayout-compose:1.1.0-alpha14")
    }
    
  2. יוצרים קובץ 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>
            
  3. 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 ו שמרכיבות את העין. הרכיב המקבל ורכיב המגדיר צריכים להתאים לדפוס מסוים. עבור לדוגמה, backgroundColor נתמך, מפני שהתצוגה כוללת getBackgroundColor() ו-setBackgroundColor().
  • המאפיין האחר שצריך לציין מבוסס על סוג הערך. אפשר לבחור מבין האפשרויות אלה הסוגים הנתמכים:
    • motion:customColorValue לצבעים
    • motion:customIntegerValue למספרים שלמים
    • motion:customFloatValue לצפים
    • motion:customStringValue למחרוזות
    • motion:customDimension למאפיינים
    • motion:customBoolean לערך בוליאני

כשמציינים מאפיין מותאם אישית, צריך להגדיר ערכים של נקודות קצה גם במאפיין ההתחלה וגם בסוף <ConstraintSet> רכיבים.

שינוי צבע הרקע

על בסיס הדוגמה הקודמת, נניח שאתם רוצים לשנות את צבעי התצוגה כחלק מהתנועה שלו, כפי שמוצג באיור 2.

איור 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 יש שאולי תרצו לציין:

  • 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: