Rouse
读完需要
9
分钟
速读仅需 3 分钟
MotionLayout能够更好的帮助我们通过xml实现动画,除了入门级的ConstraintSet、CustomAttribute,这些都是由一个start,到一个end的过渡动画。虽然它们能实现我们日常中90%的动画效果,但复杂灵活的动画,还是需要通过更高级的方法进行实现。
今天就来简单介绍MotionLayout的进阶玩法。
我们本次的目标是搞明白以下几个的用法与作用:
今天的主角都在KeyFrameSet里面,如果你需要自由操作动画每一帧的实现,就需要使用到KeyFrameSet标签。
它与之前的ConstraintSet类似,内部提供了基于帧的动画操作标签,方便开发者进行动画高度自定义。
与ConstraintSet不同的是,KeyFrameSet必须定义在TranSiton中。
<Transition
app:constraintSetStart="@+id/start"
app:duration="3000"
app:pathMotionArc="none">
<KeyFrameSet>
</KeyFrameSet>
<OnSwipe
app:dragDirection="dragDown"
app:touchAnchorId="@id/tv"
app:touchAnchorSide="bottom" />
</Transition>
这样就定义了一个KeyFrameSet标签。下来我们来使用它的帧标签来做个简单示范。
KeyPosition是提供以每帧的位置做具体动画的能力。它主要有以下几个属性:
在上篇文章中使用ConstraintSet实现了一个有左上角到右下角的简单动画。
由于ConstraintSet的性质,我们并没有定义它中间的运动轨迹,所以它的轨迹是平滑的,现在我们来使用KeyPositon来简单改变它的运行轨迹。
<Transition
app:constraintSetStart="@+id/start"
app:duration="3000"
app:pathMotionArc="none">
<KeyFrameSet>
<KeyPosition
app:framePosition="10"
app:keyPositionType="parentRelative"
app:motionTarget="@id/tv"
app:percentX="0.2"
app:percentY="0.35" />
<KeyPosition
app:framePosition="80"
app:keyPositionType="parentRelative"
app:motionTarget="@id/tv"
app:percentX="0.6"
app:percentY="0.8" />
</KeyFrameSet>
<OnSwipe
app:dragDirection="dragDown"
app:touchAnchorId="@id/tv"
app:touchAnchorSide="bottom" />
</Transition>
我们定义了三个KeyPosition,分别在它运动的10、80位置进行改变它的轨迹。轨迹具体的改变通过percentX/Y来进行。
轨迹上已经有了两个拐点,通过KeyPosition我们成功定义了动画运行效果。
注意看keyPositionType属性,我们使用的是parentRelative,另外还有deltaRelative、pathRelative。
它的作用是定义坐标系,我们默认的坐标系就是parentRelative。
它的坐标系是相对于父容器的。
这种是我们比较常有的坐标系,做动画时,以父容器为基准,更符合常规的动画操作。
更形象的其实是以左上角为原点,也是我们view的坐标系。
这个坐标系是以当前做动画的view的start为原点(0,0),end(1,1)为终点来建立的。
这种坐标系也是比较直观的,用处也比较常见。
例如,你要做start到end的过程中做一个水平或者垂直的动画,这个时候使用这个坐标系就非常简单。因为你只要操作x/y中的一个即可。
它是基于start与end作为x轴的坐标系。
看它的坐标系就很明显,它比较适合做一个基于自身start与end的弧线、曲线动画。
在上面的例子中,我们使用了pathMotionArc,并且将它的值设置为none。这样我们看到的效果就是start到帧位置、或者帧位置到帧位置、亦或者帧位置到end,它们直接的动画曲线是两点直线的连线。
这就是pathMotionArc的作用,它能够改变路径中的关键点直接的运动曲线方式。
除了none以为它还提供了其他的几种方式,我们一起来体验一下。
基于竖直方向的弧线曲线
基于水平方向的弧线曲线
基于翻转的弧线曲线
如果你针对不同的帧选择不同的pathMotionArc值,那么它的动画曲线有会更加丰富。
如果我们要操作它的运动速度,就需要用到transitionEasing,它能够改变曲线的运动速度。
目前支持的有:
如果你想自定义,也可以通过cubic来实现,例如:
app:transitionEasing="cubic(0.41, 1.97, 0.48, -1.12)"
它对应的速度曲线是:
中间速度有一个反向过程,所以我们的动画效果就是在中间时刻有个往返效果
在KeyPosition中我们能操作的属性限制在x与y,如果我们要操作一些别的属性,需要使用到KeyAttribute。
例如我们在关键帧做一个缩放效果
<KeyFrameSet>
<KeyAttribute
app:framePosition="10"
app:keyPositionType="parentRelative"
app:motionTarget="@id/tv"
android:scaleY="1.5"
android:scaleX="1.5" />
<KeyAttribute
app:framePosition="80"
app:keyPositionType="parentRelative"
app:motionTarget="@id/tv"
android:scaleY="0.5"
android:scaleX="0.5" />
</KeyFrameSet>
除了缩放,我们还可以控制它的alpha、visibility、rotation、translation等。
有了以上这些使用,我们就可以实现一些比较复杂的自定义动画,让动画的实现有了更多的选择与空间。
如果你已经掌握了这些,那么MotionLayout基本上就可以解决你所需的99%的动画效果。至于剩下的1%,归属于MotionaLayout的终极运用。
针对一块由于日常使用太少,大家基本都使用不到,就不到这里细说了,如果感兴趣可以给我留言,如果留言不较多,我也会针对性的出一篇对应的文章。
最后来个有趣的问答,我有望进8强,你能挺进几强,有望进决赛吗?