使用 MotionLayout 管理動態和小工具動畫

MotionLayout 是一種版面配置類型,可協助您管理應用程式中的動作和小工具動畫。MotionLayoutConstraintLayout 的子類別,以其豐富的版面配置功能建構而成。在 ConstraintLayout 程式庫中,MotionLayout 可做為支援資料庫使用。

MotionLayout 會彌補版面配置轉換和複雜動作處理之間的落差,提供屬性動畫架構TransitionManagerCoordinatorLayout 的組合。

圖 1.基本觸控操作。

除了說明版面配置之間的轉換外,MotionLayout 還可讓您為所有版面配置屬性建立動畫效果。此外,該程式庫本身也支援容易理解的轉場效果。這表示您可以根據某些條件 (例如觸控輸入),立即顯示轉場效果中的任何點。MotionLayout 也支援主要畫面格,能視需求完全自訂轉換效果。

MotionLayout 是完全宣告式的,也就是說,無論複雜程度為何,您都可以在 XML 中說明任何轉場效果。

設計須知

MotionLayout 的用途是移動使用者與互動的 UI 元素 (例如按鈕和標題列) 並調整大小,以及為這些元素加上動畫效果。請勿在應用程式中使用動態效果做為無謂的特殊效果。您可以運用這項資訊協助使用者瞭解應用程式的功能。如要進一步瞭解如何設計含有動態效果的應用程式,請參閱 Material Design 的「瞭解動作」一節。

開始使用

請按照下列步驟,開始在專案中使用 MotionLayout

  1. 新增 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")
    }
    
  2. 建立 MotionLayout 檔案: MotionLayoutConstraintLayout 的子類別,您可以透過取代版面配置資源檔案中的類別名稱,將任何現有的 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:constraintSetStartmotion: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
  • rotationrotationXrotationY
  • translationXtranslationYtranslationZ
  • scaleXscaleY

自訂屬性

<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 所示。

圖 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,請參閱下列資源: