我们知道,属性动画的本质是在一个时间段内,动态的改变对象的属性,从而实现动画效果,打个比方,在 10 秒之内让数字从 1 过渡到 10,这个中间的过度值是由系统计算生成,最基本的也就是每秒 +1,Android 也提供了其他的过渡方式,由 Interpolators 来完成。
确切的说,Interpolators 是一个接口,其一系列的实现类实现了各种效果的计算过程:
如果上述实现类满足不了你的需求,你还可以自定义自己的插值器,需要实现以下接口:
我们通过调用动画对象的 setInterpolators 方法为动画设置插值器。
ValueAnimator animator = ValueAnimator.ofInt(1, 10);
animator.setDuration(500);
animator.setInterpolator(new AccelerateDecelerateInterpolator());
animator.start();
我们为Animator 设置了开始值和结束值,Interpolators 又为我们提供了数值过渡的速率,那么我就可以获取到某个事件内的值是多少,Evaluator 就可以帮助我们实现这个需求。
系统提供的 Evaluator:
系统会根据我们的可变长参数自动判断是使用 IntEvaluator 还是 FlaoatEvaluator,至于 ArgbEvaluator,则是当参数为颜色值时使用。
如果这三个 Evaluator 无法满足我们的需求,还可以自定义 Evaluator,需实现 TypeEvaluator 接口:
如果想要的动画类型是 Android 系统所未知的,那么通过实现 TypeEvaluator 接口就能够创建自己的评价器。Android 系统已知的类型是 int、float 或颜色(color),分别有 IntEvaluator、FloatEvaluator 和 ArgbEvaluator 类型的评价器所支持。
在 TypeEvaluator 接口中只有一个要实现的方法:evaluate() 方法。这个方法允许正在使用的动画处理器返回一个适用于于当前动画时点动画属性值,FloatEvaluator 类演示了这个方法是如何做这件事的:
public class FloatEvaluator implements TypeEvaluator {
public Object evaluate(float fraction, Object startValue, Object endValue) {
float startFloat = ((Number) startValue).floatValue();
return startFloat + fraction * (((Number) endValue).floatValue() - startFloat);
}
}
注意:当 ValueAnimator 对象(或 ObjectAnimator 对象)运行时,它会计算当前的动画播放比例(一个 0 到 1 之间的值),然后根据你所使用的插值类型来计算一个要插入的动画的版本。插值比例是由 TypeEvaluator 对象通过 fraction 参数接收来的,因此在计算动画值的时候,不需要考虑插值。
自定义 Evaluator 用的比较少,这里是一个关于颜色变化的例子:
public class MainActivity extends AppCompatActivity {
private LinearLayout ly_root;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ly_root = (LinearLayout) findViewById(R.id.ly_root);
ObjectAnimator anim = ObjectAnimator.ofObject(ly_root, "backgroundColor", new ArgbEvaluator(), Color.parseColor("#FFDAB9"), Color.parseColor("#FF6A6A"));
anim.setRepeatCount(-1);
anim.setDuration(5000);
anim.setRepeatMode(ObjectAnimator.REVERSE);
anim.start();
Log.d("TTT", "start on:" + Color.parseColor("#FFDAB9") + " end on:" + Color.parseColor("#FF6A6A"));
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
Log.d("TTT", "color = " + animation.getAnimatedValue());
}
});
}
}