资讯详情

ConstraintLayout2.0一篇写不完之KeyCycles的秘密

点击上面的蓝字关注我,知识会给你力量

KeyCycle与KeyFrame类似,但又比KeyFrame复杂,复杂在于KeyFrame只是单帧,而且KeyCycle则是在KeyFrame在此基础上,增加了周期性处理,因此,KeyCycle核心是周期,KeyCycle决定了在Scene所有需要重复处理的操作,其核心API如下所示。

  • framePosition:作为一个KeyFrame,KeyCycle必须知道在场景的哪一点操作

  • motionTarget:指定的View ID

  • wavePeriod:周期数量

  • waveOffset:偏移开始位置

  • waveShape:Cycle的波形

image-20210827101705951

MotionLayout提供了CycleEditor帮助开发者编辑KeyCycle,下载地址如下:

https://github.com/googlesamples/android-ConstraintLayoutExamples/releases/download/1.0/CycleEditor.jar

直接执行,点击file中的parse,可以编辑区域xml转换为波形。

java-jarCycleEditor.jar 

分割Scene

在创建KeyCycle第一件事是使用不同的东西framePositions把你的Scene分为多部分组合Partial Scene,然后就可以用了wavePeriod指定你想要的每个部分的周期数waveShape指定具体的波形。

1*cdtzWO2JKu6VvmN9Ew2kvw

wavePeriod是KeyCycle最难理解的部分要掌握wavePeriod必须首先理解定义Partial Scene,Partial Scene指由前一点和后一点组成的区域,这一点非常重要。

在某个framePosition的KeyCycle中指定wavePeriod,其实就是这个Partial Scene这个区域填充了几个周期的波形。

但是这里的问题又来了,每一个framePosition都被周围的framePosition有关,那么wavePeriod不是重复计算吗?

是的。。。所以在整个过程中。Partial Scene中的wavePeriod是由Partial Scene中所有framePosition的的wavePeriod确定之和。绕是不是,是对的。

这就是为什么KeyCycle结合生成工具的原因有一个单独的原因KeyCycleEditor,还是可以理解的。

wavePeriod已经很绕了,但还在后面。

再来看看KeyCycle具体属性值中指定的含义。

例如,我们在KeyCycle中指定rotation代码如下所示为20。

<KeyCycle motion:framePosition="0" motion:target="@ id/button" motion:wavePeriod="0" motion:waveOffset="0" motion:waveShape="sin" android:rotation="20"/> 

这个rotation20是什么意思?你认为这是理所当然的framePosition属性值是20吗?太年轻了。

其实这个属性值和View在当前framePosition没有直接联系的属性值。

是不是很奇怪,的确如此,那么这玩意儿到底是干嘛的呢???

在这里,我们需要改变我们的想法,那就是KeyCycle里面设置的一切都是画出来的「波形图」,因此,这些参数的设置是为了修改波形图的具体形状。

<KeyFrameSet>  <KeyCycle motion:framePosition="0" motion:target="@ id/button" motion:wavePeriod="0" motion:waveOffset="0" motion:waveShape="sin" android:rotation="0"/>  <KeyCycle motion:framePosition="50" motion:target="@ id/button" motion:wavePeriod="1" motion:waveOffset="0" motion:waveShape="sin" android:rotation="10"/>  <KeyCycle motion:framePosition="100" motion:target="@ id/button" motion:wavePeriod="0" motion:waveOffset="0" motion:waveShape="sin" android:rotation="30"/>  </KeyFrameSet> 

这样一个KeyCycle最后形成的波形图是这样的。

image-20210827151332911

每一个都可以发现framePosition属性值是绘制波形图的峰值。

在此基础上,waveOffset很容易理解,它的作用是给予framePosition的当前value增加一个初始值,也是为了修改波形。

要干嘛

你说KeyCycle这玩意儿整这么复杂,到底有什么用呢??

我们有了KeyFrame,可用于添加中间态关键帧,因此也需要KeyCycle干嘛呢?

说到这里,我不得不提一下Monotonic Spline(单调采样),通常关键帧插值算法采用单调采样,但不能实现曲线的平滑过渡,如下图中的绿色曲线,使用单调采样,变成以下曲线,过渡将非常僵硬。

image-20210827154425111

所以为了使曲线顺利过渡,KeyCycle使用的是Typical Spline(特征采样),就像上图中的紫色曲线一样,四点顺利连接。

如果只是为了让曲线顺利过渡,那你就太小看了KeyCycle不得不说,外国人做的这些事情,总能在你觉得无关紧要的地方做得很深。

KeyCycle的核心在于波形,而波是什么呢?

image-20210827155302534

上图表示sin和cos也有几何意义sin和cos的源。

说句不像傅里叶变换的话,我们可以将一个View的曲线运动,拆解成多个不同波形运动的叠加。

例如我们对一个View的translationX同时设置sin和cos的KeyCycle,最终形成的运动轨迹,就是一个圆形!

所以,由此及彼,我们可以复合多个属性的同时,通过不同的波形叠加,实现任何你想要的运动轨迹!这TM就牛逼了啊,简直就是傅里叶变换在Android动画中的实现了。

在CycleEditor中,有一些自带的Demo,可以让你充分的了解这个思想,例如下面这个例子。

image-20210827160218065

太复杂了是吗?

CustomWave shape in keyCycle

CL2.1之后,motion:waveShape除了之前定义的sin、cos、bounce这些预设曲线外,你还可以设置自定义的波形曲线,定义方式如下所示。

<KeyCycle motion:waveShape=”spline(0.0, 1.0, -1.0, 0)” />

这就有点牛逼了,本来就很复杂了,这下还来了自定义曲线,再见。

KeyCycle确实比较强大,但是也非常复杂,强烈建议大家使用CycleEditor来学习,KeyCycle这种东西,就像核武器一样,可以不用,但是不能没有。

向大家推荐下我的网站 https://xuyisheng.top/  点击原文一键直达

专注 Android-Kotlin-Flutter 欢迎大家访问

往期推荐

  • flutter与compose的爱恨情仇

  • 从精准化测试看ASM在Android中的强势插入-读懂diff

  • 闲言碎语——第四期

  • 真·富文本编辑器的演进之路-Span的整体性控制

< END >

作者:徐宜生

标签: jku3e3变送器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

 锐单商城 - 一站式电子元器件采购平台  

 深圳锐单电子有限公司