MotionLayout
是一種版面配置類型,可協助您管理應用程式中的動作和小工具動畫。
MotionLayout 是 ConstraintLayout 的子類別,並以其豐富的版面配置功能為基礎。MotionLayout 是 ConstraintLayout 程式庫的一部分,以支援程式庫的形式提供。
MotionLayout 可彌合版面配置轉場效果與複雜動作處理之間的差距,提供介於屬性動畫架構、TransitionManager 和 CoordinatorLayout 之間的混合功能。
除了說明版面配置之間的轉場效果,MotionLayout 也可讓您為任何版面配置屬性製作動畫。此外,它也內建支援可搜尋的轉場效果。也就是說,您可以根據觸控輸入等條件,立即顯示轉場效果中的任何時間點。MotionLayout 也支援關鍵影格,可根據需求完全自訂轉場效果。
MotionLayout 全面支援宣告式機制,因此無論多麼複雜,您都可以用 XML 描述任何轉場效果。
設計須知
MotionLayout 的用途是移動、調整大小及製作動畫,適用於使用者互動的 UI 元素,例如按鈕和標題列。請勿在應用程式中使用動態效果做為無關的特殊效果。讓使用者瞭解應用程式的用途。如要進一步瞭解如何運用動態效果設計應用程式,請參閱 Material Design 專區的「瞭解動態效果」一節。
開始使用
請按照下列步驟,開始在專案中使用 MotionLayout。
-
新增
ConstraintLayout依附元件:如要在專案中使用MotionLayout,請將ConstraintLayout2.0 依附元件新增至應用程式的build.gradle檔案。如果您使用 AndroidX,請新增下列依附元件:Groovy
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檔案的完整範例,用於定義圖 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屬性會參照 MotionScene。動態場景是 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 還會插補下列屬性:
alphavisibilityelevationrotation、rotationX、rotationYtranslationX、translationY、translationZscaleX、scaleY
自訂屬性
在 <Constraint> 中,您可以使用 <CustomAttribute> 元素,為不單純與位置或 View 屬性相關的屬性指定轉場效果。
<Constraint android:id="@+id/button" ...> <CustomAttribute motion:attributeName="backgroundColor" motion:customColorValue="#D81B60"/> </Constraint>
<CustomAttribute> 包含兩個自有屬性:
motion:attributeName為必要項目,且必須與具有 getter 和 setter 方法的物件相符。getter 和 setter 必須符合特定模式。舉例來說,由於檢視畫面具有基礎getBackgroundColor()和setBackgroundColor()方法,因此支援backgroundColor。- 您必須提供的其他屬性取決於值類型。請從下列支援類型中選擇:
motion:customColorValue代表顏色motion:customIntegerValue(整數)motion:customFloatValue浮點數motion:customStringValue字串motion:customDimension個維度motion:customBoolean(布林值)
指定自訂屬性時,請在開始和結束 <ConstraintSet> 元素中定義端點值。
變更背景顏色
以上述範例為基礎,假設您希望檢視區塊的顏色隨著動作變化,如圖 2 所示。
在每個 ConstraintSet 元素中新增 <CustomAttribute> 元素,如以下程式碼片段所示:
<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,請參閱下列資源:
- Kotlin 03.2 版 Android 進階功能:透過 MotionLayout 建立動畫
- MotionLayout 範例
- GitHub 上的 MotionLayout/ConstraintLayout 範例
- MotionLayout 簡介 (第 1 部分)
- MotionLayout 簡介 (第 2 部分)
- MotionLayout 簡介 (第 III 部分)
- MotionLayout 簡介 (第 IV 部分)