Keyframes Deep Dive
MotionLayout动画同时通过截断两个状态之间的值(典型的就是控件的位置和大小)运作的, 指定使用ConstraintLayout提供的Constraint系统, 以及View的属性. 在两个状态之间的transition可以通过触控控制. 这个系统能给你的transitions提供完美的结果.
KeyFrames提供了额外的能力来定义transations, 分为如下几类:
Keyframes
及关键位置帧:在start/end两个之间某个时间点,指定一个改变信息
以下是支持的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的动画
以上我们定义了两个状态:左下角和右下角的状态,动画的路径是简单地的 linear 插件值 - 也就是沿着直线运动
为什么选择 Position Keyframes?
keyframes 表达的是一个临时短暂的改变,但是 ConstraintSet表达的是一种 “resting”态(可以理解为变化态)
keyframes 比ConstraintSet计算更加轻量级
position keyframes允许操作widget动画的路径(直线或者曲线) - 而ConstraintSets相对于其他widgets,指定一个widget的位置
以XML表述
Keyframes 包含在<KeyFrameSet>
属性中,<KeyFrameSet>
包含在MotionScene文件的<Transition>
中.Position keyframes通过tag <KeyPosition>
表示,整体的结构如下:
<Transition ...>
<KeyFrameSet>
<KeyPosition
motion:keyPositionType="parentRelative"
motion:percentY="0.25"
motion:framePosition="50"
motion:target="@+id/button"/>
</KeyFrameSet>
</Transition>
其中必要的字段:
target
: keyframe应用到的widgetframePosition
: keyframe应用的时机[0,1]keyPositionType
: 使用的坐标系统parentRelative, deltaRelative, pathRelative
percentX / percentY
: 此位置的 (x,y) 坐标
坐标系统介绍
parentRelative
坐标相对于parent的计算
deltaRelative
坐标相对于end widget计算
pathRelative
坐标相对于start-end 之间的直线计算
Arc Motion
ConstraintLayout 2.0.0 alpha 2 引入了更易使用的,完美的曲线动画的方式 - 只需要引入 motion:pathMotionArc 属性到ConstraintSet中,就能将默认的 linear motion 转换成 arc motion.
motion:pathMotionArc=”startHorizontal”配置的效果
motion:pathMotionArc=”startVertical”配置的效果
可以通过加入 position keyframes 来实现更复杂的动画,例如在在屏幕中间插入一个 keyframe
<KeyPosition
motion:keyPositionType="parentRelative"
motion:percentY="0.5"
motion:framePosition="50"
motion:target="@id/button"/>
效果如下:
也可通过控制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
Accelerate easing
Decelerate easing
Attributes Keyframes
见上篇文章已经有详细的解释