MotionLayout เป็นเลย์เอาต์ประเภทหนึ่งที่ช่วยคุณจัดการการเคลื่อนไหวและภาพเคลื่อนไหววิดเจ็ตในแอป MotionLayout เป็นคลาสย่อยของ ConstraintLayout และสร้างขึ้นจากความสามารถของเลย์เอาต์ที่หลากหลาย MotionLayout เป็นส่วนหนึ่งของไลบรารี ConstraintLayout จึงมีให้บริการเป็นไลบรารีสนับสนุน
MotionLayout เป็นตัวเชื่อมระหว่างการเปลี่ยนเลย์เอาต์กับการจัดการการเคลื่อนไหวที่ซับซ้อน โดยนำเสนอฟีเจอร์ที่ผสมผสานระหว่างเฟรมเวิร์กภาพเคลื่อนไหวของพร็อพเพอร์ตี้, TransitionManager และ CoordinatorLayout
นอกเหนือจากการอธิบายการเปลี่ยนรูปแบบระหว่างเลย์เอาต์แล้ว MotionLayout ยังให้คุณทำให้พร็อพเพอร์ตี้เลย์เอาต์เคลื่อนไหวได้ด้วย นอกจากนี้ ยังรองรับทรานซิชันที่กรอได้อยู่แล้ว ซึ่งหมายความว่าคุณสามารถแสดงจุดใดก็ได้ภายในทรานซิชันโดยอิงตามเงื่อนไขบางอย่าง เช่น อินพุตการสัมผัส MotionLayout ยังรองรับเฟรมหลักด้วย ซึ่งช่วยให้คุณปรับแต่งทรานซิชันได้ตามต้องการ
MotionLayout เป็นคำสั่งแบบสมบูรณ์ ซึ่งหมายความว่าคุณสามารถอธิบายการเปลี่ยนผ่านใน XML ได้อย่างซับซ้อนเพียงใดก็ได้
ข้อควรพิจารณาเกี่ยวกับการออกแบบ
MotionLayout มีไว้สำหรับย้าย ปรับขนาด และทำให้องค์ประกอบ UI เคลื่อนไหวซึ่งผู้ใช้โต้ตอบด้วย เช่น ปุ่มและแถบชื่อ อย่าใช้ภาพเคลื่อนไหวในแอปเป็นเอฟเฟกต์พิเศษที่ไม่จำเป็น ใช้เพื่อช่วยให้ผู้ใช้ได้ทราบว่าแอปของคุณทําอะไรอยู่ ดูข้อมูลเพิ่มเติมเกี่ยวกับการออกแบบแอปด้วยการเคลื่อนไหวได้ที่ส่วนการทำความเข้าใจการเคลื่อนไหวใน Material Design
เริ่มต้นใช้งาน
ทำตามขั้นตอนต่อไปนี้เพื่อเริ่มใช้ MotionLayout ในโปรเจ็กต์
-
เพิ่ม Dependency
ConstraintLayout: หากต้องการใช้MotionLayoutในโปรเจ็กต์ ให้เพิ่ม DependencyConstraintLayout2.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แบบเต็ม ซึ่งกำหนดเลย์เอาต์ที่แสดงในรูปที่ 1AndroidX
<?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>1 รายการสําหรับปลายทางแต่ละจุดของการเคลื่อนไหว ปลายทางเหล่านี้จะวางอยู่กึ่งกลางแนวตั้งโดยใช้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> มีแอตทริบิวต์ 2 รายการ ได้แก่
motion:attributeNameต้องระบุและต้องตรงกับออบเจ็กต์ที่มีเมธอด getter และ setter Getter และ Setter ต้องตรงกับรูปแบบที่เฉพาะเจาะจง ตัวอย่างเช่น ระบบรองรับbackgroundColorเนื่องจากมุมมองมีวิธีการgetBackgroundColor()และsetBackgroundColor()อยู่เบื้องหลัง- แอตทริบิวต์อื่นๆ ที่คุณต้องระบุจะขึ้นอยู่กับประเภทค่า เลือกจากประเภทที่รองรับต่อไปนี้
motion:customColorValueสำหรับสีmotion:customIntegerValueสำหรับจำนวนเต็ม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"ระบุว่าจะใช้ฉากที่มีการเคลื่อนไหวหรือไม่ ค่าเริ่มต้นสำหรับแอตทริบิวต์นี้คือtrueapp:showPaths="boolean"ระบุว่าจะแสดงเส้นทางการเคลื่อนไหวขณะที่การเคลื่อนไหวทำงานอยู่หรือไม่ ค่าเริ่มต้นสำหรับแอตทริบิวต์นี้คือfalseapp: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 (ส่วนที่ 1)
- ข้อมูลเบื้องต้นเกี่ยวกับ MotionLayout (ส่วนที่ 2)
- ข้อมูลเบื้องต้นเกี่ยวกับ MotionLayout (ส่วนที่ 3)
- ข้อมูลเบื้องต้นเกี่ยวกับ MotionLayout (ส่วนที่ 4)