盒子
盒子
文章目录
  1. KeyFrameSet
  2. KeyPosition
  3. keyPositionType
    1. parentRelative
    2. deltaRelative
    3. pathRelative
  4. pathMotionArc
    1. startVertical
    2. startHorizontal
    3. filp
  5. transitionEasing
  6. KeyAttribute
  7. 🐑🐑🐑
  8. 推荐

MotionLayout进阶动画必修课

MotionLayout能够更好的帮助我们通过xml实现动画,除了入门级的ConstraintSet、CustomAttribute,这些都是由一个start,到一个end的过渡动画。虽然它们能实现我们日常中90%的动画效果,但复杂灵活的动画,还是需要通过更高级的方法进行实现。

今天就来简单介绍MotionLayout的进阶玩法。

我们本次的目标是搞明白以下几个的用法与作用:

  1. KeyFrameSet
  2. KeyPositon
  3. keyPositonType
  4. pathMotionArc
  5. transitionEasing
  6. KeyAttribute

KeyFrameSet

今天的主角都在KeyFrameSet里面,如果你需要自由操作动画每一帧的实现,就需要使用到KeyFrameSet标签。

它与之前的ConstraintSet类似,内部提供了基于帧的动画操作标签,方便开发者进行动画高度自定义。

与ConstraintSet不同的是,KeyFrameSet必须定义在TranSiton中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<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

KeyPosition是提供以每帧的位置做具体动画的能力。它主要有以下几个属性:

  1. motionTarget:作用的view对应的id
  2. framePostion:具体帧位置,开始到结束,值范围为0~100。
  3. percentX/Y:基于当前坐标系的比例,值为 -1 ~ 1
  4. keyPositionType:当前以使用的坐标系,目前支持的有,parentRelative、deltaRelative、pathRelative。

在上篇文章中使用ConstraintSet实现了一个有左上角到右下角的简单动画。

由于ConstraintSet的性质,我们并没有定义它中间的运动轨迹,所以它的轨迹是平滑的,现在我们来使用KeyPositon来简单改变它的运行轨迹。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<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

注意看keyPositionType属性,我们使用的是parentRelative,另外还有deltaRelative、pathRelative。

它的作用是定义坐标系,我们默认的坐标系就是parentRelative。

parentRelative

它的坐标系是相对于父容器的。

这种是我们比较常有的坐标系,做动画时,以父容器为基准,更符合常规的动画操作。

更形象的其实是以左上角为原点,也是我们view的坐标系。

deltaRelative

这个坐标系是以当前做动画的view的start为原点(0,0),end(1,1)为终点来建立的。

这种坐标系也是比较直观的,用处也比较常见。

例如,你要做start到end的过程中做一个水平或者垂直的动画,这个时候使用这个坐标系就非常简单。因为你只要操作x/y中的一个即可。

pathRelative

它是基于start与end作为x轴的坐标系。

看它的坐标系就很明显,它比较适合做一个基于自身start与end的弧线、曲线动画。

pathMotionArc

在上面的例子中,我们使用了pathMotionArc,并且将它的值设置为none。这样我们看到的效果就是start到帧位置、或者帧位置到帧位置、亦或者帧位置到end,它们直接的动画曲线是两点直线的连线。

这就是pathMotionArc的作用,它能够改变路径中的关键点直接的运动曲线方式。

除了none以为它还提供了其他的几种方式,我们一起来体验一下。

startVertical

基于竖直方向的弧线曲线

startHorizontal

基于水平方向的弧线曲线

filp

基于翻转的弧线曲线

如果你针对不同的帧选择不同的pathMotionArc值,那么它的动画曲线有会更加丰富。

transitionEasing

如果我们要操作它的运动速度,就需要用到transitionEasing,它能够改变曲线的运动速度。

目前支持的有:

  1. linear
  2. standard
  3. accelerate
  4. decelerate

如果你想自定义,也可以通过cubic来实现,例如:

1
app:transitionEasing="cubic(0.41, 1.97, 0.48, -1.12)"

它对应的速度曲线是:

中间速度有一个反向过程,所以我们的动画效果就是在中间时刻有个往返效果

KeyAttribute

在KeyPosition中我们能操作的属性限制在x与y,如果我们要操作一些别的属性,需要使用到KeyAttribute。

例如我们在关键帧做一个缩放效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<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强,你能挺进几强,有望进决赛吗?

推荐

android_startup: 提供一种在应用启动时能够更加简单、高效的方式来初始化组件,优化启动速度。不仅支持Jetpack App Startup的全部功能,还提供额外的同步与异步等待、线程控制与多进程支持等功能。

AwesomeGithub: 基于Github的客户端,纯练习项目,支持组件化开发,支持账户密码与认证登陆。使用Kotlin语言进行开发,项目架构是基于JetPack&DataBinding的MVVM;项目中使用了Arouter、Retrofit、Coroutine、Glide、Dagger与Hilt等流行开源技术。

flutter_github: 基于Flutter的跨平台版本Github客户端,与AwesomeGithub相对应。

android-api-analysis: 结合详细的Demo来全面解析Android相关的知识点, 帮助读者能够更快的掌握与理解所阐述的要点。

daily_algorithm: 每日一算法,由浅入深,欢迎加入一起共勉。

支持一下
赞赏是一门艺术