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-alpha13" // To use constraintlayout in compose implementation "androidx.constraintlayout:constraintlayout-compose:1.1.0-alpha13" }
Kotlin
dependencies { implementation("androidx.constraintlayout:constraintlayout:2.2.0-alpha13") // To use constraintlayout in compose implementation("androidx.constraintlayout:constraintlayout-compose:1.1.0-alpha13") }
-
建立
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 簡介 (第 I 部分)
- MotionLayout 簡介 (第 II 部分)
- MotionLayout 簡介 (第 III 部分)
- MotionLayout 簡介 (第 IV 部分)