Property Animation中最重要,最基础的一个类就是ValueAnimator了。Property Animation利用ValueAnimator来跟踪记录对象属性已经变化了多长时间及当前这个时间点的值。
而在ValueAnimator中,又封装了两个类:
1)TimeInterpolator,也称插值器,是来计算当前动画运动的一个跟时间有关系的比例因子。
2)TypeEvaluator,这个就是利用TimeInterpolator计算出来的因子来算出当前动画运行到的位置。
这样讲太抽象了,我们还是先用自然语言来描述一下整个动画的过程吧。
动画的原理,其实就是一帧帧的画面顺着时间顺序,在我们眼中形成视觉残留的效果。所以在动画中,时间的概念是很重要的,只有时间的变化,才能形成动画效果。
0)动画准备开始,我们在这里设置了一个动画的时长(duration),如果不设置的话,动画的时长就是300毫秒,每个画面显示的时间是10ms。同时也设置了某个属性值在这个时间段中变化的起始值start和结束值end,意思就是说,在duration时间中,属性值要从start 变化到 end。
1)动画开始了,过了 t 时间,ValueAnimator会根据 t / duration 算出一个时间消逝的比例因子(elapsed fraction),意思就是说,现在时间到 t了,我们假设总的时间的duration就是3t吧,那就是现在已经过了1/3时间了,那这个属性值也应该要变化到1/3了。
2)动画继续,现在到了2t了,那么现在动画时间已经过了2/3了,那么这个属性值是不是已经变化到2/3了呢。
3)现在到了3t了,动画结束了,属性值就已经从start变成end值了。
那么现在问题来了,如果都是这样算的话,那动画不就一直是很匀速的了吗?是的,如果用的是LinearInterpolator的话。
TimeInterpolator
2)AccelerateInterpolator:一直加速。
3)AnticipateInterpolator:先往后一下,再嗖的一声一往无前。
4)AnticipateOvershootInterpolator:先往后一下,再一直往前超过终点,再往回收一下。
5)BounceInterpolator:最后像个小球弹几下。
6)CycleInterpolator:重复几次,感觉就是环形进度条那种,具体我还没试过。
7)DecelerateInterpolator:一直减速。
8)LinearInterpolator:线性,这个就是我们上面讲到的很均匀的了。
9)OvershootInterpolator:到了终点之后,超过一点,再往回走。有个参数可以定义,超过的力度。
public float getInterpolation(float input) { return input; }而 AccelerateDecelerateInterpolator 则会利用余弦函数的对称性变化计算这个比例因子,如下:
public float getInterpolation(float input) { return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f; }
TypeEvaluator
class BezierEvaluator implements TypeEvaluator<PointF>{ @Override public PointF evaluate(float fraction, PointF startValue, PointF endValue) { final float t = fraction; float oneMinusT = 1.0f - t; PointF point = new PointF(); PointF point0 = (PointF)startValue; PointF point1 = new PointF(); point1.set(width, 0); PointF point2 = new PointF(); point2.set(0, height); PointF point3 = (PointF)endValue; point.x = oneMinusT * oneMinusT * oneMinusT * (point0.x) + 3 * oneMinusT * oneMinusT * t * (point1.x) + 3 * oneMinusT * t * t * (point2.x) + t * t * t * (point3.x); point.y = oneMinusT * oneMinusT * oneMinusT * (point0.y) + 3 * oneMinusT * oneMinusT * t * (point1.y) + 3 * oneMinusT * t * t * (point2.y) + t * t * t * (point3.y); return point; } }
自定义TypeEvaluator,我们必须实现其evaluate方法,目的就是计算出目前的对象对应属性的值,而它会接收三个参数,一个是上文中通过interpolator算出的比例,还有我们在创建动画时设置的起始值和结束值。
ValueAnimator.AnimatorUpdateListener
valueAnimator.addUpdateListener(new AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { PointF pointF = (PointF)animation.getAnimatedValue(); button.setX(pointF.x); button.setY(pointF.y); } });
我们在这里改变Button的X坐标和Y坐标,从而改变其具体的位置。至于validate,然后引起重新绘制的过程,对于这些基本的属性,ValueAnimator已经帮我们实现了。