Android MotionLayout详解

文章目录

  • 一、前言
  • 二、使用入门
    • 2.1 引入依赖
    • 2.2 创建 MotionLayout 布局文件
    • 2.3 创建 MotionScene(运动描述文件)
    • 2.4 在 MotionLayout 中配置运动描述
    • 2.5 MotionLayout 的属性详解
  • 三、运动描述文件详解
    • 3.1 描述文件组成元素
    • 3.2 元素详解
      • 3.2.1
        • 必须包含的元素
        • 可以包含的元素
        • 属性
      • 3.2.2
        • 语法
        • 必须包含的元素
        • 父元素
        • 属性
      • 3.2.3
        • 语法
        • 父元素
        • 属性
      • 3.2.4
        • 语法
        • 属性
        • 可以包含的元素
        • 父元素
      • 3.2.5
        • 语法
        • 属性
      • 3.2.6
        • 语法
        • 属性
        • 父元素
      • 3.2.7
        • 语法
        • 父元素
        • 可以包含的元素
      • 3.2.8
        • 语法
        • 属性
        • 父元素
      • 3.2.9
        • 语法
        • 属性
        • 父元素
    • 3.3 设置视图属性
      • 3.3.1 插入标准属性
      • 3.3.2 自定义属性
  • 四、编后语

一、前言

    MotionLayout 其实是一种布局类型,可帮助您管理动画。MotionLayoutConstraintLayout的子类(关于 ConstraintLayout 的介绍可以参考: Android ConstraintLayout从入门到精通),因此, MotionLayout 拥有者 ConstraintLayout 同样强大的布局功能,它是 ConstraintLayout 库的一部分,可向后兼容 API 级别 14,也就是说,只需要引入 ConstraintLayout 的依赖,就可以使用 MotionLayout 了。

    MotionLayout 将布局转换与复杂动画处理结合在一起,同时也在属性动画框架、TransitionManagerCoordinatorLayout 之间提供了各种功能。

    除了描述布局之间的转换之外,MotionLayout 还能够为任何布局属性添加动画效果。此外,它本身就支持可搜索转换。也就是说,可以根据某个条件(例如触控输入)立即显示转换中的任意点。MotionLayout 还支持关键帧,从而实现完全自定义的转换以满足您的需求。

    此外,MotionLayout 是完全声明性的,也就是说可以直接使用 XML 描述任何转换,无论复杂程度如何。

注意:MotionLayout 仅适用于为其直接子级添加动画,不支持嵌套布局层次结构或 Activity 转换。

二、使用入门

2.1 引入依赖

    MotionLayoutConstraintLayout 库的一部分,所以,只需要在程序模块的 build.gradle 文件中增加 ConstraintLayout 库的依赖就可以。

// support包引入,如果项目使用其他support包,使用这个
implementation 'com.android.support.constraint:constraint-layout:1.1.3'

// androidx包引入,如果项目使用androidx时使用,跟support包引入只能选其一,否则会冲突
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta7'

2.2 创建 MotionLayout 布局文件

    前面提到,MotionLayoutConstraintLayout 的子类,所以,直接将布局中的 ConstraintLayout 类接替换成 MotionLayout 也是完全可以的。


<androidx.constraintlayout.motion.widget.MotionLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:tools="http://schemas.android.com/tools"
    tools:showPaths="true">
    <View
        android:id="@+id/btn6"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="@color/colorAccent"
        android:text="Button6"/>
androidx.constraintlayout.motion.widget.MotionLayout>

2.3 创建 MotionScene(运动描述文件)

    MotionLayout 是完全声明性的,使用 XML 文件描述任何转换,MotionLayout 的转换描述 XML 文件放在 res/xml 目录下,其中包含相应布局的所有运动描述。为了将布局信息与运动描述分开,每个 MotionLayout 都引用一个单独的 MotionScene

注意:MotionScene 中的定义的运动描述优先于 MotionLayout 中的任何类似定义。


<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/btn6"
            motion:touchAnchorSide="right"
            motion:dragDirection="dragRight" />
    Transition>

    <ConstraintSet android:id="@+id/start">
        <Constraint
            android:id="@+id/btn6"
            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"
            motion:layout_constraintVertical_bias="0.5"
            android:layout_marginLeft="8dp" >

            <CustomAttribute
                motion:attributeName="backgroundColor"
                motion:customColorValue="#D81B60" />
        Constraint>
    ConstraintSet>

    <ConstraintSet android:id="@+id/end">
        <Constraint
            android:id="@+id/btn6"
            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="#FFFF00" />
        Constraint>
    ConstraintSet>
MotionScene>

提示:运动描述文件通过预定义的元素,声明运动的各种状态,关于描述文件的详细内容,请参考:运动描述文件详解

2.4 在 MotionLayout 中配置运动描述

    创建运动描述文件之后,需要在布局文件中添加配置。添加运动描述配置,需要在 MotionLayout 跟节点上,通过 layoutDescription 属性配置。


<androidx.constraintlayout.motion.widget.MotionLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:tools="http://schemas.android.com/tools"
    app:layoutDescription="@xml/scene_01"
    tools:showPaths="true">
    <View
        android:id="@+id/btn6"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="@color/colorAccent"
        android:text="Button6"/>
androidx.constraintlayout.motion.widget.MotionLayout>
  • 效果:
    Android MotionLayout详解_第1张图片

注意事项:运动描述文件和布局是一一对应的,一个 MotionLayout 需要但对对应一个描述 XML 文件,并且描述文件中的所有控件的 ID 也必须在布局中能找到。

2.5 MotionLayout 的属性详解

    MotionLayout 除了上述的 layoutDescription 属性以外,还有以下属性:
其他 MotionLayout 属性
除了上述示例中的属性之外,MotionLayout 还包含您可能想要指定的其他属性:

  • applyMotionScene:布尔类型,表示是否应用 MotionScene,默认值为 true。
  • showPaths:布尔类型,表示在运动进行时是否显示运动路径。默认值为 false。
  • progress:float类型,可以明确指定转换进度(取值0.0~1.0)
  • currentState:reference类型,可指定具体的 ConstraintSet
  • motionDebug:可显示与运动有关的其他调试信息。可取值有:SHOW_PROGRESSSHOW_PATHSHOW_ALL

三、运动描述文件详解

3.1 描述文件组成元素

  • :描述文件的根节点元素。
  • :声明所有的视图控件在运动过程中,特定关键点的位置和属性。
  • :声明单个视图控件在运动过程中,特定关键点的位置和属性。
  • :声明运动过程中的开始和结束状态,包括所有预期的过度状态、用户的触发的交互等。
  • :声明当用户触摸特定的视图控件时所要执行的动作。
  • :声明当用户在布局中滑动时所要执行的动作。
  • :声明在运动过程中视图控件的位置和属性。
  • :声明在运动过程中特定时刻视图控件的位置。
  • :声明在运动过程中特定时刻视图控件的属性。

3.2 元素详解

3.2.1

    是运动场景文件的根元素,必须包含一个或多个 元素,元素用于定义运动序列的开始和结束状态,以及这两种状态之间的转换。

  • 语法
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:motion="http://schemas.android.com/apk/res-auto"
    motion:defaultDuration="500">
MotionScene>

必须包含的元素

  1. :指定运动场景需要的动画序列,可以有多个,每一个指定需要执行的运动序列。如果 包含多个 元素,MotionLayout 会根据用户的互动选择最合适的 元素,但是要注意防止冲突。

可以包含的元素

  1. :运动的状态布局集,为 元素指定开始或结束状态。 MotionLayout 关联的 可以没有 子元素,因为 可指向 XML 布局,而不是指向布局集。

属性

  1. defaultDuration:所有动画的默认持续时间(以毫秒为单位)。用于给未指定持续时间的 指定一个默认的持续时间。

3.2.2

     元素是用来指定视图在动画序列中某一点上的位置和属性(可同时指定多个视图),也叫约束条件集合。通常,一个 元素可指向两个 元素,其中一个定义动画序列的开始,另一个定义动画序列的结束。

语法

 
    ...

ConstraintSet>

必须包含的元素

  1. :必须包含一个或者多个 元素,描述动画在特定时刻视图的位置和属性。

父元素

属性

  1. android:id:集合的 ID,在 中通过此 ID 来引用该序列。
  2. deriveConstraintsFrom:(可选)值为另一个 ConstraintSet 的 ID。如果指定这个属性,ID 对应约束集合内的所有约束条件都将应用于此集合,除非此集明确替换它们。
  • 示例:

<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:motion="http://schemas.android.com/apk/res-auto"
    motion:defaultDuration="500">

    <Transition
        motion:constraintSetStart="@+id/start"
        motion:constraintSetEnd="@+id/end2"
        motion:duration="1000">
        <OnSwipe
            motion:touchAnchorId="@+id/btn6"
            motion:touchAnchorSide="right"
            motion:dragDirection="dragRight" />
    Transition>


    <ConstraintSet android:id="@+id/start">
        <Constraint
            android:id="@+id/btn6"
            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"
            motion:layout_constraintHorizontal_bias="0.5"
            android:layout_marginLeft="8dp" >

            <CustomAttribute
                motion:attributeName="backgroundColor"
                motion:customColorValue="#D81B60" />
        Constraint>
        <Constraint
            android:id="@+id/btn5"
            android:layout_width="64dp"
            android:layout_height="64dp"
            android:layout_marginStart="8dp"
            android:layout_marginBottom="8dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintStart_toStartOf="parent"
            android:layout_marginLeft="8dp" >

            <CustomAttribute
                motion:attributeName="backgroundColor"
                motion:customColorValue="#D8FF22" />
        Constraint>

    ConstraintSet>

    <ConstraintSet android:id="@+id/end2"
        motion:deriveConstraintsFrom="@+id/end">
    ConstraintSet>

    <ConstraintSet android:id="@+id/end">
        <Constraint
            android:id="@+id/btn6"
            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="#FFFF00" />
        Constraint>

        <Constraint
            android:id="@+id/btn5"
            android:layout_width="64dp"
            android:layout_height="64dp"
            android:layout_marginEnd="8dp"
            android:layout_marginTop="8dp"
            motion:layout_constraintEnd_toEndOf="parent"
            motion:layout_constraintTop_toTopOf="parent" >
            <CustomAttribute
                motion:attributeName="backgroundColor"
                motion:customColorValue="#FF00FF" />
        Constraint>
    ConstraintSet>
MotionScene>

以上例子中,ID 为 end2 的 ConstraintSet 包含了 ID 为 end 的 ConstraintSet 中所有的约束。如果在 end2 对同一个视图声明约束(Constraint),那么就会替换掉 end 中声明的对应约束。

3.2.3

     元素用来声明运动序列其中一个视图的位置和属性,也就是视图的约束。

语法

<Constraint
    android:id="@+id/view_id_name"
    attributes>
Constraint>

父元素

属性

  1. android:id:视图 ID,约束视图的 ID ;
  2. 其他在 ConstraintLayout 中用来约束视图位置的属性;

3.2.4

    该元素是用来声明运动过程中的开始和结束状态,包括所有预期的过度状态、用户的触发的交互等。

语法


    ...
    [动画触发属性元素]
Transition>

属性

  1. motion:constraintSetStart:运动序列的初始状态。可以是 的 ID (属性值设置为“@+id/constraintSetId”),也可以是布局(属性值设置为"@layout/layoutName”)。
  2. motion:constraintSetEnd:运动序列的最终状态。可以是 的 ID (属性值设置为“@+id/constraintSetId”),也可以是布局(属性值设置为"@layout/layoutName”)。
  3. motion:duration:运动序列的时长(单位:毫秒,可选)。如果未指定,则使用 元素中的 defaultDuration 属性值。

可以包含的元素

  1. :表示运动序列是由用户轻触触发的。
  2. :表示运动序列是由用户滑动触发的。
  3. :用于为运动序列中的元素指定一个或多个中间位置或属性设置。

父元素

3.2.5

    该元素用于指定当用户点按特定视图时要执行的操作,用于 元素内部,指定当用户点击视图时触发动画序列,在一个 内部只能有一个 元素。

说明:官方文档中说一个 元素内部可以有多个 元素,但是笔者实践过程中发现不可行,会编译报错,不知道是否跟版本有关。

语法

<OnClick
    motion:targetId="@+id/view_id"
    motion:clickAction="actionName" />

属性

  1. motion:targetId:点击的视图的 ID。
  2. motion:clickAction:点击时触发的操作,enum 类型,可选值有:
取值 说明 备注
transitionToStart 从当前状态转变到 元素中 motion::constraintSetStart 属性指定的状态,转变过程有动画效果 -
transitionToEnd 从当前状态转变到 元素中 motion:constraintSetEnd 属性指定的k状态,转变过程有动画效果。 -
jumpToStart 从当状态转变到 元素中 motion::constraintSetStart 属性指定的状态,转变过程无动画效果 -
jumpToEnd 从当状态转变到 元素中 motion:constraintSetEnd 属性指定的状态,转变过程无动画效果 -
toggle 元素中 motion::constraintSetStartmotion:constraintSetEnd 两个属性指定的两个状态中相互转换,转变过程有动画效果 只要在非这两个状态下,触发都会向目标状态的相反状态转变。例如:当动画执行到中间状态时,触发时,将不会到达当前动画的目标状态,而是立刻向当前动画的目标状态的相反状态转变

3.2.6

    该元素用于指定当用户在不居中滑动时需要执行的操作。动画序列的速度和目标视图的动画,受滑动的速度和方向影响,滑动的速度和方向是通过可选参数配置来控制的。

说明:官方文档中说一个 元素内部可以有多个 元素,但是笔者实践过程中发现不可行,会编译报错,不知道是否跟版本有关。

语法

<onSwipe
    motion:touchAnchorId="@id/target_view"
    motion:touchAnchorSide="side"
    [ motion:dragDirection="direction" ]
    [ motion:dragScale="scale" ]
    [ motion:maxVelocity="maxVelocity" ]
    [ motion:maxAcceleration="maxAcceleration" ]
    [ motion:onTouchUp="action" ] />

属性

  1. motion:touchAnchorId:滑动时需要移动的视图 ID。
  2. motion:touchAnchorSide:滑动所关联到的目标视图的锚点边,MotionLayout 会尝试在该锚点点与用户手指之间保持恒定的距离。(可取值有: leftrighttopbottom)。
  3. motion:dragDirection:用户滑动的方向,如果设定了该值,这个 将仅支持像特定的方向滑动(可取值有:dragLeftdragRightdragUpdragDown
  4. motion:dragScale:控制目标视图的滑动距离和用户手指滑动距离的相对比例,默认值是1。取值小于1时目标视图的移动速度小于手指滑动速度,取值大于1时目标视图的移动速度大于手指的滑动速度。
  5. motion:maxVelocity:目标视图的最大速度。
  6. motion:maxAcceleration:目标视图的最大加速度。
  7. motion:onTouchUp:触摸收起时的动作,可选值有:stop(停止动画)、autoComplete(自动完成动画)、autoCompleteToEnd(自动完成到结束状态)、autoCompleteToStart(自动完成到开始状态)、decelerate(减速停止动画)、decelerateAndComplete(减速并完成动画)、

父元素

3.2.7

    前面提到,动画的声明是有 “开始状态” 和 “结束状态” 两个点,目标控件在这两个点之间移动,前面的例子都是直线的动画,显然这个实际使用中需要更复杂的动画。 就是提供声明更加复杂动画的元素,他声明了动画运动轨迹的关键点集合,它可包含 ,通过这些元素,可以在动画的 “开始状态” 和 “结束状态” 添加 “中间点”,动画将平滑地移动到每个中间点,完成更复杂的动画。

语法

<KeyFrameSet>
    [ <KeyPosition/>... ]
    [ <KeyAttribute/>...]
KeyFrameSet>

父元素

可以包含的元素

3.2.8

    该元素用于指定视图在运动过程中,在特定的时刻的位置。换句话说就是运动轨迹上的关键点的位置。在一个 中可以添加多个 用来添加多个不同的关键点位置。

语法

<KeyPosition
    motion:motionTarget="@id/targetView"
    motion:framePosition="frame position percentage"
    motion:keyPositionType="position type"
    motion:percentX="xOffset"
    motion:percentY="yOffset"
    />

属性

  1. motion:motionTarget:当前关键点位置控制的目标视图的 ID。
  2. motion:framePosition:关键帧位置,用百分比表示,取值为 0~100 之间的整数。(例如:取值20,表示该关键帧在运动轨迹的 20% 位置处 ),这个点将运动时间一分为二,两边的时间是相等的,如果运动轨迹长度不一样,那么将会造成运动速度不一样。但需要注意的是,关键帧的位置并不是关键点的位置。
  3. motion:keyPositionType:关键点的类型,不同的类型会对 motion:percentXmotion:percentY 的值做出不一样的解析。取值有 parentRelativedeltaRelativepathRelative
  4. motion:percentX:X 轴方向的属性取值百分比,取值范围为0.0~1.0。
  5. motion:percentY:Y 轴方向的属性取值百分比,取值范围为0.0~1.0。

  • 关键点类型详细说明

    • parentRelative :父容器关系型,即关键点的位置是相对于整个父容器中的相对位置来指定,percentXpercentY 分别表示 X 轴和Y轴相对位置,取值为 -1.0~1.0(负数时目标视图将移动到父容器外面)。需要注意的是:关键点的位置是相对父容器来指定,跟 “开始点” 和 “结束点” 位置无关。
    • deltaRelative:三角区域关系型,在目标视图整个运动序列移动的区域组成一个坐标轴,X 为横轴,Y 为纵轴,原点为 “开始点”,视图移动的方向为坐标的正方向。percentXpercentY 分别为 X 轴和 Y 轴上的数值,控制关键点的位置,取值范围是 -1.0 ~ 1.0之间,负数表示在坐标轴的负值方向位置。framePosition 一样控制的是轨迹弧顶的位置。
    • pathRelative:路径关系型,即关键点的位置是相对于路径相对指定的,路径是指 “开始点” 和 “结束点” 的直线路径(构成 X 轴),percentX 表示在 X 轴相对位置,0 表示在开始点, 1表示在结束点;percentY 表示垂直于 X 轴(Y 轴)的相对位置,正数在 X 轴左侧,负数在 X 轴右侧。 |percentY 取值范围为-1.0~1.0,Y 轴距离是以 “开始点” 和 “结束点”之间的距离为基数的百分比(也就是说 Y 轴的最大距离就是开始点和结束点直线距离的最大值,如果该值取0,弧度为0,则轨迹为直线)。另外, framePosition 控制的是轨迹弧顶的位置(而不是关键点的位置),大于 50 时偏向起始点,小于50时偏向结束点,弧顶两端轨迹,运动时间是相等的,如果取了不对等的值(非50),就可以实现快慢变化的效果。
  • deltaRelative示例

    • 示例代码

<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:motion="http://schemas.android.com/apk/res-auto"
    motion:defaultDuration="2000">
    <Transition
        motion:constraintSetStart="@+id/btn7_start"
        motion:constraintSetEnd="@+id/btn7_end">
        <KeyFrameSet>
            <KeyPosition
                motion:motionTarget="@+id/btn7"
                motion:framePosition="25"
                motion:keyPositionType="deltaRelative"
                motion:percentX="0.5"
                motion:percentY="-0.2"/>
            <KeyPosition
                motion:motionTarget="@+id/btn7"
                motion:framePosition="75"
                motion:keyPositionType="deltaRelative"
                motion:percentX="0.4"
                motion:percentY="0.6"/>
        KeyFrameSet>
    Transition>
    <ConstraintSet
        android:id="@+id/btn7_start">
        <Constraint
            android:id="@+id/btn7"
            android:layout_width="80dp"
            android:layout_height="80dp"
            motion:layout_constraintTop_toTopOf="parent"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintLeft_toLeftOf="parent"/>
    ConstraintSet>
    <ConstraintSet
        android:id="@+id/btn7_end">
        <Constraint
            android:id="@+id/btn7"
            android:layout_width="80dp"
            android:layout_height="80dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintRight_toRightOf="parent" />
    ConstraintSet>
MotionScene>
  • 效果(虚线为运动轨迹,中间的方点为关键点)
    Android MotionLayout详解_第2张图片

父元素

3.2.9

     元素是用来在运动序列的特定时刻,设置视图的任何 标准属性。必须注意的是,只能设置标准属性

语法


属性

  1. motion:motionTarget:设置属性的目标视图 ID
  2. motion:framePosition:目标视图在序列中具有指定属性的帧位置,取值范围是 0 ~ 100 之间的整数(虽然是指定某个帧位置,但是动画会自动对属性的效果进行过度,而不是生硬的切换为该属性的效果)。
  3. 可选的标准属性有:
  • android:alpha:视图的透明度
  • android:elevation:视图的 Z 轴深度(在 API Level 21开始才有,像素单位,如dp)
  • android:rotation:视图的旋转角度(默认方向)
  • android:rotationX:视图 X 轴方向旋转角度
  • android:rotationY:视图 Y 轴方向旋转角度
  • android:scaleX:视图 X 轴方向缩放
  • android:scaleY:视图 Y 轴方向缩放
  • android:translationX:视图 X 轴方向的平移量(像素单位,如dp)
  • android:translationY:视图 Y 轴方向的平移量(像素单位,如dp)
  • android:translationZ:视图 Z 轴方向的平移量(在 API Level 21开始才有,像素单位,如dp)

说明:通过 元素可以设置关键点位置的标准属性,但是在开始位置和结束位置,可以设置视图的属性(包含标准属性和自定义属性),更多详情参考:设置视图属性

父元素

3.3 设置视图属性

     前面提到可以通过在 元素中使用 元素在关键点设置标准属性,改变视图的样式,在 元素包含的子元素中,也可以设置视图的属性,改变视图样式,包括标准属性和自定义属性。

3.3.1 插入标准属性

     在 元素中可包含标准属性,用于设置视图在改状态下的样式。

  • 示例:

<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:motion="http://schemas.android.com/apk/res-auto"
    motion:defaultDuration="2000">
    <Transition
        motion:constraintSetStart="@+id/btn7_start"
        motion:constraintSetEnd="@+id/btn7_end">
        <OnSwipe
            motion:touchAnchorId="@+id/btn7"
            motion:touchAnchorSide="bottom"
            motion:dragDirection="dragDown"
            motion:maxVelocity="2"/>

        <KeyFrameSet>
            <KeyPosition
                motion:motionTarget="@+id/btn7"
                motion:framePosition="25"
                motion:keyPositionType="deltaRelative"
                motion:percentX="0.5"
                motion:percentY="-0.2"/>
            <KeyPosition
                motion:motionTarget="@+id/btn7"
                motion:framePosition="75"
                motion:keyPositionType="deltaRelative"
                motion:percentX="0.4"
                motion:percentY="0.6"/>
        KeyFrameSet>
    Transition>
    <ConstraintSet
        android:id="@+id/btn7_start">
        <Constraint
            android:id="@+id/btn7"
            android:layout_width="80dp"
            android:layout_height="80dp"
            motion:layout_constraintTop_toTopOf="parent"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintLeft_toLeftOf="parent"
            android:rotation="45"
            android:alpha="0.2">
        Constraint>
    ConstraintSet>
    <ConstraintSet
        android:id="@+id/btn7_end">
        <Constraint
            android:id="@+id/btn7"
            android:layout_width="80dp"
            android:layout_height="80dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintRight_toRightOf="parent"
            android:rotation="145"
            android:alpha="1.0">
        Constraint>
    ConstraintSet>
MotionScene>
  • 效果

  • 标准属性包括:

    • android:alpha:视图的透明度
    • android:visibility:视图是否可见
    • android:elevation:视图的 Z 轴深度(在 API Level 21开始才有,像素单位,如dp)
    • android:rotation:视图的旋转角度(默认方向)
    • android:rotationX:视图 X 轴方向旋转角度
    • android:rotationY:视图 Y 轴方向旋转角度
    • android:scaleX:视图 X 轴方向缩放
    • android:scaleY:视图 Y 轴方向缩放
    • android:translationX:视图 X 轴方向的平移量(像素单位,如dp)
    • android:translationY:视图 Y 轴方向的平移量(像素单位,如dp)
    • android:translationZ:视图 Z 轴方向的平移量(在 API Level 21开始才有,像素单位,如dp)

3.3.2 自定义属性

     在 元素中,您可以使用 元素设置属性,自定义属性不仅仅可以设置标准属性,也可以设置非标准的相关属性(例如:backgroundColor 背景色),但是必须要注意一点,设置的自定义属性,必须是在 View 中定义了 gettersetter 方法的,而且属性值的类型必须准确。

一个 元素必须包含两个属性:

  • motion:attributeName:属性名(必须)
  • 必须包含以下含类型的属性值的一个:
    • motion:customColorValue: 适用于颜色
    • motion:customIntegerValue:适用于整数
    • motion:customFloatValue:适用于浮点值
    • motion:customStringValue:适用于字符串
    • motion:customDimension:适用于尺寸
    • motion:customBoolean:适用于布尔值

注意事项:
1. 属性名必须正确,且这个属性必须包含对外的 gettersetter 方法,否则自定义属性无效=;
2. 属性值必须选择正确的类型,否则自定义属性无效(可以查看 setter 方法中的参数类型选择正确的类型)。

  • 示例:

<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:motion="http://schemas.android.com/apk/res-auto"
    motion:defaultDuration="2000">
    <Transition
        motion:constraintSetStart="@+id/btn7_start"
        motion:constraintSetEnd="@+id/btn7_end">
        <OnClick
            motion:targetId="@+id/btn_start"
            motion:clickAction="toggle" />

        <KeyFrameSet>
            <KeyPosition
                motion:motionTarget="@+id/btn7"
                motion:framePosition="25"
                motion:keyPositionType="deltaRelative"
                motion:percentX="0.5"
                motion:percentY="-0.2"/>
            <KeyPosition
                motion:motionTarget="@+id/btn7"
                motion:framePosition="75"
                motion:keyPositionType="deltaRelative"
                motion:percentX="0.4"
                motion:percentY="0.6"/>
        KeyFrameSet>
    Transition>

    <ConstraintSet
        android:id="@+id/btn7_start">
        <Constraint
            android:id="@+id/btn7"
            android:layout_width="80dp"
            android:layout_height="80dp"
            motion:layout_constraintTop_toTopOf="parent"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintLeft_toLeftOf="parent"
            android:alpha="0.2">
            <CustomAttribute
                motion:attributeName="backgroundColor"
                motion:customColorValue="@color/colorAccent" />
            <CustomAttribute
                motion:attributeName="rotation"
                motion:customFloatValue="45.0" />
        Constraint>
    ConstraintSet>
    <ConstraintSet
        android:id="@+id/btn7_end">
        <Constraint
            android:id="@+id/btn7"
            android:layout_width="80dp"
            android:layout_height="80dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintRight_toRightOf="parent"
            android:alpha="1.0">
            <CustomAttribute
                motion:attributeName="backgroundColor"
                motion:customColorValue="@color/colorPrimary" />
            <CustomAttribute
                motion:attributeName="rotation"
                motion:customFloatValue="145.0" />
        Constraint>
    ConstraintSet>
MotionScene>
  • 实现效果

示例讲解:以上的示例中,使用 元素添加了两个自定义属性,分别是 backgroundColorrotation,这两个属性均有公开的 gettersetter 方法(setBackgroundColor()setRotation()),所以自定义属性有效,其中 backgroundColor 是非标准属性,rotation 是标准属性(可以直接在 元素中设置)。

四、编后语

     MotionLayout 在动画处理方面的能力非常强大,完全配置化,如果需要在布局中使用到动画的同学可以试试这个强大的布局。

你可能感兴趣的:(Android开发)