<声明>
转载请保留本来源地址:
http://blog.csdn.net/wzg_1987/article/details/8989686
在使用动画Animation或者AnimationSet的时候,有一个interpolator插补器的属性。可以用来设置动画运动时的速率。那么,插补器是怎么实现一个动画的速率改变的呢?
在讲这些之前,我想先补充说点,动画插补器目前都只是对动画执行过程的时间进行修饰,并没有对轨迹进行修饰。因为所有的插补器都是实现了Interpolator这个接口,而Interpolator又是继承自一个叫做TimeInterpolator的接口(从3.0开始,增加了TimeInterpolator这个接口,并把原先的Interpolator接口的抽象方法移到了其中,3.0后的Interpolator接口也就什么也没做,只是对父类改了个名字,达到向下兼容)。
插补器的原理就是通过改变实际执行动画的时间点,提前/延迟执行默认的时间点来达到加速/减速的效果。(所以,有些朋友可能想通过它来实现一些特定的轨迹,这并不能达到目的。至少目前的api是不支持的。最多通过设置负时间/大于1的时间比,来使控件按设定的动画轨迹反方向/超出改变一点轨迹。)
在Interpolator的实现类里面,都实现了一个float getInterpolator(float input)的方法。传入参数是正常执行动画的时间点,返回值是用户真正想要它执行的时间点。传入参数是0~1,返回值一般也是0~1。(0~1)表示整段动画的过程。中间的0.2、0.3等小数表示在整个动画(原本是匀速的)中的位置,其实就是一个比值。如果返回值是负数,会沿着相反的方向执行。(如果是alpha值,返回负数会有点问题,因为alpha值比较特殊,本身只能是0~1,并不是一个循环的周期,如果取了负值,这就很难确定了,要看android是怎么计算alpha值的。)如果返回的是大于1,会超出正方向执行。同样,如果是alpha值,也存在不确定的效果。
简单点解释这个方法,就是当要执行input的时间时,给它另外一个时间,让系统执行另外一个时间的效果。
比如:
在加速插补器里面,这个重载方法是这样的:
public float getInterpolation(float input) { if (mFactor == 1.0f) { return input * input; } else { return (float)Math.pow(input, mDoubleFactor); } }mFactor其实一直都是1,因为配置文件并没有提供设置其它值的入口,默认会是1。mDoubleFactor是2,由此可见,这个方法其实就是个x^2的曲线。当input=0.3时,返回值=0.09,假如这个动画的总时长是1秒,也就是说,在0.3秒的时候只是执行0.09秒时候的效果。这样说可能还有点难理解。
其实这个速度和x^2这条抛物线的斜率的变化是有关的,和斜率的变化率是正比关系。比如,上面这个加速插补器的曲线就如下图:
红色的那条是正常的时间-实际时间变化曲线:g(x)=x;实际时间是按照正常时间匀速变化的,斜率是常数1.而抛物线在[0,1]时,斜率先是0,再慢慢增加的。也就是在0时,执行的时间是0,在0.1时,执行的时间(位置)依然是接近于0的时间点(执行的位置)。执行的时间一直比正常该执行的时间点迟。但是执行的时间变化的增量也一直在变,而且越变越快,也就是斜率一直在变大,这导致了感官上看到了一个加速的过程。它起步的速度是一样的,但是它把原本该执行的时间提前执行/或者推迟执行,由此产生速度不一致。
另附系统提供的其它几个插补器的曲线图:
1.AccelerateDecelerateInterpolator 加速减速插补器
取值是[0,1],可见,从原点开始,斜率是0,先圆滑地慢慢增大,再慢慢减小,最后返回值还是1。这就是一个先加速再减速的效果。而且整个过程是平滑变化的。这也是数学的奥妙啊。
2.DecelerateInterpolator 减速插补器
明显,虽然斜率一直是大过正常值(因为开始时执行较快,后来才慢慢回归正常时间,但直到最后一刻才回到),但斜率一直在减小,是一个减速的过程。
3.AnticipateInterpolator 向前插补器
这是一条符合g(x)=3x^3-2x^2的曲线。前面2/3秒之前(假设整个过程是1秒),返回值是负数。如果这是一个直线运动的动画,这段时间会向设定的相反的方向运动一点,而且速度显得稍缓(反方向先加速再减速)。这之后以一个较快速度跑到终点(大概0.7秒时会回到原点)。
4.AnticipateOvershootInterpolator 向前向后插补器
这是3条曲线合并起来的图,我们只需要较深色的那条x轴上[0,0.5)和稍浅那条[0.5,1]这两段就可以。可以看到,前面一点时间有一段负数的返回值,而后面有一段大于1的返回值,这就有了向前向后的效果。
5.OvershootInterpolator 超出插补器
开始时有个加速过程,超出边界后,速度慢慢降下来,最后返回到终点。
总之,斜率大于1速度就比正常快,小于1比正常慢,小于0往反方向运动。斜率变大就加速,斜率变小就减速(但速度不一定比正常慢)。
还有循环插补器CycleInterpolator 和反弹插补器BounceInterpolator,基本原理都一样,只是函数图象需要做更细的分段处理,这里就不做介绍了。
(转载请注明本来源,谢谢合作)