原始文章地址

Keyframes Deep Dive

MotionLayout动画同时通过截断两个状态之间的值(典型的就是控件的位置和大小)运作的, 指定使用ConstraintLayout提供的Constraint系统, 以及View的属性. 在两个状态之间的transition可以通过触控控制. 这个系统能给你的transitions提供完美的结果.

KeyFrames提供了额外的能力来定义transations, 分为如下几类:

Keyframes

及关键位置帧:在start/end两个之间某个时间点,指定一个改变信息
MotionLayout III - 图1

以下是支持的Keyframe类型

  • Position keyframe : KeyPosition

  • Attribute keyframe : KeyAttribute

  • Cycle keyframe : KeyCycle

  • TimeCycle keyframe : KeyTimeCycle(注: alpha2 版本中才添加)

通用属性解释

所有的keyframes (包括Position, Attribute, Cycle, TimeCycle) 共享的通用属性:

  • motion:framePosition : keyframe应用到的转换点[0,100]

  • motion:target : 受keyframe影响的对象

  • motion:transitionEasing : easing curve的使用(默认是 linear)

  • motion:curveFit : spline (default) or linear —  keyframes使用的曲线插值器

Position Keyframes

position keyframes可能是最常遇到使用的keyframes. 其允许我们在transition过程中,在占据的屏幕中去改变widget的路径信息. 例如下图简单包裹在 MotionLayout 中的widget的动画
MotionLayout III - 图2
以上我们定义了两个状态:左下角和右下角的状态,动画的路径是简单地的 linear 插件值 - 也就是沿着直线运动

下图是定义的 弧线运行路径实例:
MotionLayout III - 图3

为什么选择 Position Keyframes?

  • keyframes 表达的是一个临时短暂的改变,但是 ConstraintSet表达的是一种 “resting”态(可以理解为变化态)

  • keyframes 比ConstraintSet计算更加轻量级

  • position keyframes允许操作widget动画的路径(直线或者曲线) - 而ConstraintSets相对于其他widgets,指定一个widget的位置

以XML表述

Keyframes 包含在<KeyFrameSet>属性中,<KeyFrameSet> 包含在MotionScene文件的<Transition>中.Position keyframes通过tag <KeyPosition> 表示,整体的结构如下:

  1. <Transition ...>
  2. <KeyFrameSet>
  3. <KeyPosition
  4. motion:keyPositionType="parentRelative"
  5. motion:percentY="0.25"
  6. motion:framePosition="50"
  7. motion:target="@+id/button"/>
  8. </KeyFrameSet>
  9. </Transition>

其中必要的字段:

  • target: keyframe应用到的widget

  • framePosition: keyframe应用的时机[0,1]

  • keyPositionType: 使用的坐标系统 parentRelative, deltaRelative, pathRelative

  • percentX / percentY : 此位置的 (x,y) 坐标

坐标系统介绍

  • parentRelative

MotionLayout III - 图4 坐标相对于parent的计算

  • deltaRelative

MotionLayout III - 图5
坐标相对于end widget计算

  • pathRelative

MotionLayout III - 图6
坐标相对于start-end 之间的直线计算

Arc Motion

ConstraintLayout 2.0.0 alpha 2 引入了更易使用的,完美的曲线动画的方式 - 只需要引入 motion:pathMotionArc 属性到ConstraintSet中,就能将默认的 linear motion 转换成 arc motion.

motion:pathMotionArc=”startHorizontal”配置的效果
MotionLayout III - 图7

motion:pathMotionArc=”startVertical”配置的效果
MotionLayout III - 图8

可以通过加入 position keyframes 来实现更复杂的动画,例如在在屏幕中间插入一个 keyframe

<KeyPosition
    motion:keyPositionType="parentRelative"
    motion:percentY="0.5"
    motion:framePosition="50"
    motion:target="@id/button"/>

效果如下:
MotionLayout III - 图9

也可通过控制motion:pathMotionArc属性来决定某个Keyframe的路径样式:

  • flip:翻转弧度的方向

  • none:去掉弧度

  • startHorizontal

  • startVertical

Easing

在前面的章节中,覆盖了定义一个动画路径的多个机制原理,看出一个动画不仅仅是动画路径,其时间线也是很关键的。因为position keyframes 在时间线上是很特殊的,因此可以定义一个widget运动的快慢,完全取决于移动的距离。但是在单个片段中 - start、end状态之间,或者keyframes之间 - 时间线是线性的。

可以通过使用motion:transitionEasing属性,指定一个缓和曲线(easing curve)去改变它。你可以在ConstraintSets和keyframes上使用这个属性,其值可以如下:

  • cubic(float, float , float, float)参数x1,y1,x2,y2,代表立方贝塞尔曲线控制点从0,0 到 1,1 的控制点

  • 就一直使用关键字standard, accelerate, decelerate代表预设的curve值

Standard easing

MotionLayout III - 图10
cubic(0.4, 0.0, 0.2, 1)

Accelerate easing

MotionLayout III - 图11
cubic(0.4, 0.0, 1, 1)

Decelerate easing

MotionLayout III - 图12
cubic(0.0, 0.0, 0.2, 1)

Attributes Keyframes

上篇文章已经有详细的解释