MotionLayout
是一種版面配置類型,可協助您管理應用程式中的動畫和小工具動畫。MotionLayout
是 ConstraintLayout
的子類別,可利用其豐富的版面配置功能。在 ConstraintLayout
程式庫中,MotionLayout
可做為支援資料庫使用。
MotionLayout
可彌補版面配置轉場和複雜動態處理之間的差距,在屬性動畫架構、TransitionManager
和 CoordinatorLayout
之間提供多種功能。
除了說明版面配置之間的轉場效果,MotionLayout
還可讓您為任何版面配置屬性設定動畫。此外,它本身也支援可暫停的轉場效果。這表示您可以根據某些條件 (例如觸控輸入),立即顯示轉場效果中的任何點。MotionLayout
也支援關鍵影格,可讓您根據需求自訂轉場效果。
MotionLayout
是完全宣告式,也就是說,您可以在 XML 中描述任何轉場,不論其複雜程度為何。
設計須知
MotionLayout
旨在移動、調整大小及為使用者互動的 UI 元素 (例如按鈕和標題列) 製作動畫。請勿在應用程式中使用動態效果做為不必要的特殊效果。使用這項功能可協助使用者瞭解應用程式正在執行的操作。如要進一步瞭解如何設計含有動畫的應用程式,請參閱 Material Design 的「瞭解動畫」一節。
開始使用
請按照下列步驟,開始在專案中使用 MotionLayout
。
-
新增
ConstraintLayout
依附元件:如要在專案中使用MotionLayout
,請將ConstraintLayout
2.0 依附元件新增至應用程式的build.gradle
檔案。如果您使用的是 AndroidX,請新增下列依附元件:Groovy
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 必須符合特定模式。舉例來說,由於檢視畫面具有基礎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 簡介 (第 3 部分)
- MotionLayout 簡介 (第 IV 部分)