上一篇文章,大概介绍了一下View Animation以及Property Animation的使用。这一篇,在简单使用的基础之上,进行一点高级的技巧。
TypeEvaluator
当我们使用ValueAnimator或者ObjectAnimator时,会有一个ofObject()方法和setEvaluator()。在这个方法中是有一个TypeEvaluator参数的。。那么这个TypeEvaluator的作用到底是什么呢?我们在使用ValueAnimator.ofFloat()时是会向其中传入开始值以及结束值的。然后系统就会帮助我们平滑计算出整个过程的数值。
我们可以看一下系统中的实现,系统中其实实现了几个TypeEvaluator。当我们使用ofFloat()时调用的默认是FloatEvaluator。使用ofInt()默认的是IntEvaluator。使用ofArgb()默认的是ArgbEvaluator。
|
|
可以看到FloatEvaluator实现了TypeEvaluator,并且TypeEvaluator其中只有一个方法evaluate(float fraction, Number startValue, Number endValue)。这个方法中有三个值,后两个分别是我们在ofFloat(startValue,endValue)传进来的。而第一个值fraction呢?它其实是一个当前动画执行进度的这么一个参数。所以,上面evaluator方法就很明白了。就是fraction在动画执行过程中是变化的执行进度,假如现在开始值是0,结束值是100,动画执行了50%。那么此时返回的值就应该是0 + 0.5 * (100 - 0)= 50。所以,TypeEvaluator就是执行如何从初始值 过渡到 结束值 的逻辑。那么,这个变化的fraction从哪里来呢?这就要用到Interpolator了。我们后面介绍。
知道了原理,我们就可以打造自己的TypeEvaluator了。
|
|
这里先新建一个Point类,记录View的x坐标以及y坐标。
|
|
自己定义了一个PointEvaluator,在其中计算了在动画执行过程中View的坐标值,并封装为Point对象。
|
|
这里使用ofObject()方法,传入自定义的TypeEvaluator,开始点,结束点。之后在监听器中不断的取值,这个值就是我们在自定义TypeEvaluator中计算出来的x,y值。然后,得到Point对象中,就含有x,y值。
接下来就是取出Point中的x,y值,然后不断的在onDraw()方法中绘制,就出现了一个圆自上而下运动。

现在,让我们来做一些修改,然小球在下落过程中不断变换颜色。
|
|
上面的实现是应用了系统提供的ArgbEvaluator(),这个方法是系统帮助我们处理颜色过渡的,只要我们提供颜色的开始值以及结束值。之后在动画监听中得到颜色过渡中的值,并且设置给画笔就可以了:
|
|
当然,也可以这样:
|
|
看一下,两者的实现:
ofObject:
|
|
ofArgb:
|
|
看一下,其实实现相同的。
以上都是利用ValueAnimator实现的,那么ObjectAnimator可以吗?
上篇说过ObjectAnimator是通过调用属性的setter和getter方法改变属性的值,实现动画效果的。所以,我们需要自己写一个setter以及getter方法。
|
|
这里,我们使用int值表现画笔的颜色,并在setter方法中将其设置给画笔。最后,通过 invalidate(),不断调用onDraw()方法,实现颜色过渡的动画效果。
接下来,就是如何调用color了,如何对给定的颜色进行过渡了。所以,这里还要请出TypeEvaluator了。
|
|
这里我们就借鉴一下系统的ArgbEvaluator的实现方法。
ArgbEvaluator:
|
|
我们来看一下它的颜色过渡的算法:

看一下上图,经过四次与运算得到了颜色值,两位一个颜色值。开始颜色值和结束颜色值获取方式一致。最后返回 开始颜色值 + 当前进度值 * (结束颜色值 - 开始颜色值) 。这样之后,又左移刚才右移的位数,进行还原。然后,四组有做了或运算。这样一番,就得到了颜色的过渡效果。
分析完了之后,到了使用之时:
|
|

Interpolator
Interpolator,插值器。与前面的TypeEvaluator,估值器。一起实现了属性动画的各种效果。与TypeEvaluator根据开始值以及结束值进行平滑的过渡不同的是,Interpolator是用来决定值得变化趋势的,即可以先加速后减速,也可以先减速后加速。当我们步设置任何Interpolator时,系统会默认使用AccelerateDecelerateInterpolator的。这个AccelerateDecelerateInterpolator就是一个先加速后减速的效果的。
|
|
TimeInterpolator 实现了很多的类,AccelerateDecelerateInterpolator也是其中之一。看一下,实现方法中就一个getInterpolation(float input)方法。所以,想要自定义Interpolator 只要处理这一个方法就行了。
下面看一个最简单的线性的Interpolator:
|
|
之所以说其简单,是因为getInterpolation中只是返回了input未做任何处理。所以,其值得变化率是常量,就是一个匀速运动。
再看一下AccelerateDecelerateInterpolator的实现:
|
|
可以看到,这个AccelerateDecelerateInterpolator实现的就要复杂了,用到了数学中的余弦函数来模拟先加速再减速的过程。因为input的值是从0到1的。0代表动画开始点,1代表动画结束:
A value between 0 and 1.0 indicating our current point in the animation where 0 represents the start and 1.0 represents the end
所以,整个余弦之内的取值是由 π 到 2 π 的。算出值就是由 -1 到 1。所以整个返回值是由 0 到 1 。但是我们知道余弦函数由 π 到 2 π 斜率是由小到大再到小的,也就是中间的斜率最大,值得变化率也就是最大的。
上面的gif动画,小球直直的掉落,不符合现实生活。但是,系统帮助我们提供了一个BounceInterpolator可以模拟出一个反弹的效果。

现在,我们也来自定义一个Interpolater:
|
|
上面就自定义了一个先增大,再减小的过程。原谅我数学不好╮(╯﹏╰)╭。。。。。。
使用,只要setInterpolator就行了:
|
|
最后,看一下效果:

可以看到中间速度很快,最后又很慢。
ViewPropertyAnimator
属性动画的功能确实强大,但是如果我们只想改变View进行动画操作。如:进行透明度的更改:
|
|
是不是有点麻烦了,所以于在Android 3.1系统当中补充了ViewPropertyAnimator这个机制。可以理解为ViewPropertyAnimator为一种简化的Property Animation。专门为View进行动画操作。
现在,只要这样:
|
|
而且是每一个方法返回的是自身,所以支持连缀写法,所以只要一句话就完成了N个属性的更改:
|
|
而且,并不需要我们手动调用start()方法,因为在内部已经隐形调用了。当然,你想要写也可以写上start()方法的。
好了,这一篇就到这里。
参考: