จัดการการเคลื่อนไหวและภาพเคลื่อนไหวของวิดเจ็ตด้วย MotionLayout

MotionLayout เป็นประเภทเลย์เอาต์ที่ช่วยคุณจัดการการเคลื่อนไหวและภาพเคลื่อนไหวของวิดเจ็ตในแอป MotionLayout เป็นคลาสย่อยของ ConstraintLayout และต่อยอดจาก เลย์เอาต์ ในฐานะที่เป็นส่วนหนึ่งของไลบรารี ConstraintLayout MotionLayout มีให้บริการเป็นไลบรารีการสนับสนุน

MotionLayout เชื่อมช่องว่างระหว่างการเปลี่ยนเลย์เอาต์และการเคลื่อนไหวที่ซับซ้อน การจัดการ โดยเสนอคุณลักษณะแบบผสมระหว่างภาพเคลื่อนไหวของพร็อพเพอร์ตี้ เฟรมเวิร์ก TransitionManager และ CoordinatorLayout

รูปที่ 1 การเคลื่อนไหวที่ควบคุมด้วยการสัมผัสแบบพื้นฐาน

นอกจากการอธิบายการเปลี่ยนระหว่างเลย์เอาต์แล้ว MotionLayout ยังช่วยให้คุณ ทำให้คุณสมบัติของเลย์เอาต์เคลื่อนไหว นอกจากนี้ Google Analytics ยังสนับสนุน ที่ค้นหาได้ ทรานซิชัน ซึ่งหมายความว่าคุณสามารถแสดงจุดใดก็ได้ในช่วงการเปลี่ยนผ่านนี้ได้ทันที ซึ่งอิงตามเงื่อนไขบางอย่าง เช่น การป้อนข้อมูลด้วยการสัมผัส MotionLayout ยังรองรับ คีย์เฟรม ช่วยให้เปลี่ยนการกำหนดเองได้เต็มที่เพื่อให้เหมาะกับความต้องการของคุณ

MotionLayout เป็นการประกาศอย่างสมบูรณ์ หมายความว่าคุณสามารถอธิบายการเปลี่ยนแปลงใดๆ ใน XML ไม่ซับซ้อน

ข้อควรพิจารณาในการออกแบบ

MotionLayout มีไว้เพื่อย้าย ปรับขนาด และทำให้องค์ประกอบ UI เคลื่อนไหว ที่ผู้ใช้โต้ตอบกับกัน เช่น ปุ่มและแถบชื่อเรื่อง อย่าใช้การเคลื่อนไหวในแอปเป็น สร้างผลกระทบพิเศษโดยไม่จำเป็น ใช้ฟีเจอร์นี้เพื่อช่วยให้ผู้ใช้เข้าใจว่าแอปของคุณคืออะไร ลงมือทำ สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการออกแบบแอปด้วยการเคลื่อนไหว โปรดดู ส่วนดีไซน์ Material การทำความเข้าใจ การเคลื่อนไหว

เริ่มต้นใช้งาน

ทำตามขั้นตอนต่อไปนี้เพื่อเริ่มใช้ MotionLayout ในโปรเจ็กต์

  1. เพิ่มทรัพยากร Dependency ConstraintLayout: เพื่อใช้งาน MotionLayout ในโปรเจ็กต์ของคุณ ให้เพิ่ม ConstraintLayout 2.0 ทรัพยากร Dependency สำหรับแอปของคุณ build.gradle ไฟล์ หากคุณใช้ AndroidX ให้เพิ่ม ทรัพยากร Dependency ต่อไปนี้

    ดึงดูด

    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")
    }
    
  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. สร้าง 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> จำนวน 1 รายการกำหนดไว้สำหรับ และแต่ละจุดปลายทางการเคลื่อนไหว ปลายทางเหล่านี้อยู่ตรงกลางในแนวตั้ง โดยใช้ 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> มีแอตทริบิวต์ของตัวเอง 2 ตัว ได้แก่

  • ต้องระบุ motion:attributeName และต้องตรงกับออบเจ็กต์กับ Getter และ Setter Method Getter และ Setter ต้องตรงกับรูปแบบที่เฉพาะเจาะจง สำหรับ ตัวอย่างเช่น backgroundColor ได้รับการสนับสนุน เนื่องจากมุมมองนี้มี getBackgroundColor() และ setBackgroundColor() เมธอด
  • แอตทริบิวต์อื่นๆ ที่ต้องระบุจะขึ้นอยู่กับประเภทค่า เลือกจาก ประเภทที่รองรับต่อไปนี้
    • motion:customColorValue สำหรับสี
    • motion:customIntegerValue สำหรับจำนวนเต็ม
    • motion:customFloatValue สำหรับ Float
    • 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 เพิ่มเติม

นอกจากแอตทริบิวต์ในตัวอย่างก่อนหน้านี้ 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 ได้ในแหล่งข้อมูลต่อไปนี้