记录一下属性动画设计原理

动画按照大类分为属性动画、逐帧动画、补间动画。其中属性动画使用的是比较普遍的,比如平移,缩放、旋转等效果都可以使用属性动画实现。最近有在观看大佬的手撸属性动画视频,把其中的关键点记录下来。

我们如何使用属性动画,比如我们想让一个view在3s中实现放大两倍后再回到初始大小,可以这样做

 ObjectAnimator objectAnimator = ObjectAnimator.
                ofFloat(view, "scaleX", 1f,2f,1f);
        objectAnimator.setInterpolator(new LinearInterpolator());
        objectAnimator.setDuration(3000);
        objectAnimator.start();

注意,在ofFloat中传入三个参数,第一个参数是我们的view,第二个是我们要执行的属性,scaleX为X轴缩放,这里的值不能随便填,而是必须是我们view的setter、getter方法实现的才可以。第三个参数是不定值,第一个1f表示view初始大小,假设为100px,第二个2f为放大两倍为200px,第三个1f为在200px的基础上缩小为100px。

那么执行完以后为什么能够达到这样的放大缩小的效果,这些1f,2f,1f在底层是怎么体现的呢,在这3s钟内是如何分配放大缩小呢?差值器是什么意思?带着这些疑问,手撸开始。

(1)其实在动画中这些1f、2f、1f被称为"关键帧",

(2)我们能够实现view的缩放其实就是对view的属性进行不断的调整,动态的改变它的位置,而通知它改变的源头就是VSYNC信号,每隔16ms通知view更新一次,如果是2s,计算count = 2000/16为125次,也就是执行完动画需要做125更新,每一次更新都会通过反射动态改变view的位置。

(3)"关键帧"中记录当前动画的百分比计做fraction,第一帧1f为0,第二帧2f对应0.50,第三帧1f对应1.从第一个关键帧到第二个关键帧之间,计算公式为 position/(length-1) .因为第一个关键帧百分比为0,所以从二个开始计算,所以为length-1。。那么第一个1f中fraction为0.。第二个fraction为0.5。第三个fraction为1。

(4)两个关键帧之间又会分为无数的小帧,由一个差值器计算当前进行的百分比,比如是匀速差值器,在第一个关键帧1f和第二个关键帧2f之间,那么当第一个16ms信号到来时,当前view的执行百分比为1/125 = 0.008。第二个16ms为0.016,以此类推。所以百分比是通过差值器计算而来,当然为加速差值器时百分比会做加速变化,而不是匀速。

(5)当获取这个百分比以后,会将它交给估值器(源码类TypeEvaluator)计算当前view的位置,估值器中需要三个参数,当前关键帧1f,下一个关键帧2f,以及当前view百分比fraction。计算公式如下:

/**
* fraction:当前view百分比
* startValue:开始关键帧值    
* endValue:下一个关键帧值
* startFloat 为开始关键帧对应位置100px
* endValue.floatValue() 为下移关键帧对应位置200px
* 如果 startValue=1f,endValue=2f,那么开始 1f对应view位置 100px,
执行到第一个16ms信号时,view的位置为  100px+0.008*(200px-100px) = 100.8px

* 注:当从2f--》1f时 endValue.floatValue() - startFloat为-100,那么返回的值会减少,
达到缩放
*/
public Float evaluate(float fraction, Number startValue, Number endValue) {
        float startFloat = startValue.floatValue();
        return startFloat + fraction * (endValue.floatValue() - startFloat);
    }

通过公式计算得view的位置为100.8px,通过反射将view移动到该位置。

总结:

  • 动画执行是由系统VSYNC信号唤醒的,每隔16ms执行一次
  • 动画的每个关键帧存储了百分比,值类型,以及值等信息
  • 差值器是计算当前view在信号来临时执行的百分比
  • 估值器是计算当前view所在的位置,由当前关键帧和下一个关键帧以及百分比计算而来。
  • 动画执行通过反射,动态设置view的位置

猜你喜欢

转载自blog.csdn.net/qinbin2015/article/details/89226874
今日推荐