使用 MotionLayout 管理运动和微件动画

MotionLayout 是一种布局类型,可帮助您管理应用中的运动和 widget 动画。 MotionLayout 是以下类的子类 ConstraintLayout,并以其丰富的资源 布局功能作为 ConstraintLayout 库的一部分,MotionLayout 作为支持库提供。

MotionLayout 弥合了布局转换和复杂运动之间的差距 处理,在属性动画之间提供一系列功能 框架TransitionManagerCoordinatorLayout

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
图 1.基本的触控运动。

除了描述布局之间的转换之外,MotionLayout 还可让您 为任何布局属性添加动画效果此外,它本身支持可搜索 过渡效果。也就是说,您可以立即显示转场效果中的任意时间点 根据某种条件(例如触控输入)进行调整。MotionLayout 还支持 支持完全自定义的转场效果,以满足您的需求。

MotionLayout 是完全声明性的,这意味着您可以描述 不管有多复杂

设计考虑事项

MotionLayout 旨在对符合以下条件的界面元素进行移动、调整大小和添加动画效果: 例如按钮和标题栏。请勿将应用中的动作 这种无用的特殊效果使用这些信息来帮助用户了解您的应用 工作内容如需详细了解如何设计具有动态效果的应用,请参阅 Material Design 部分了解 动作

开始使用

请按照以下步骤开始在您的项目中使用 MotionLayout

  1. 添加 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")
    }
    
  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. 在之前的 MotionLayout创建 MotionScene 例如,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 必须与特定模式匹配。对于 例如,支持 backgroundColor,因为视图具有底层 getBackgroundColor()setBackgroundColor() 方法。
  • 您必须提供的另一个属性基于值类型。可供选择的选项: 支持的类型: <ph type="x-smartling-placeholder">
      </ph>
    • motion:customColorValue 适用于颜色
    • motion:customIntegerValue 适用于整数
    • motion:customFloatValue 适用于浮点值
    • motion:customStringValue 适用于字符串
    • motion:customDimension 适用于尺寸
    • motion:customBoolean 适用于布尔值

指定自定义属性时,请同时定义起始位置和 <ConstraintSet> 元素的结尾。

更改背景颜色

基于上一个示例,假设您希望视图的颜色改变 作为运动的一部分,如图 2 所示。

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
图 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,请参阅以下资源: