Android动画应用---自定义属性动画

在上篇博客中对Android动画的基本使用方法做了简介,下面学习下Android自定义属性动画。自定义Android属性动画中涉及两个关键类TypeEvaluator和TimeInterpolator ,这两个都是接口类型,下面分别介绍这个两个类型:
一、TypeEvaluator 估值器

1、作用
告诉动画系统,如何从属性初始值过渡到属性结束值。Android系统中提供的估值器有:ArgbEvaluator, FloatArrayEvaluator, FloatEvaluator, IntArrayEvaluator, IntEvaluator, PointFEvaluator, RectEvaluator。从类名称可以看出都对应什么样的属性。
自定义TypeEvaluator时需要实现evaluate()方法,下面先看下IntEvaluator的关键代码,指定属性类型为Integer对象:
[java]view plain copy

  1. public class IntEvaluator implements TypeEvaluator {
  2. public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
  3. int startInt = startValue;
  4. return (int)(startInt + fraction * (endValue - startInt));
  5. }
  6. }
  • fraction:分数(0~1),用于表示动画的完成度的。像数学中斜率的概念。
  • startValue:动画的初始值。
  • endValue:动画的终止值。
在看下RectEvaluator的关键代码,逻辑很简单:

[java]view plain copy
  1. public class RectEvaluator implements TypeEvaluator {
  2. @Override
  3. public Rect evaluate(float fraction, Rect startValue, Rect endValue) {
  4. int left = startValue.left + (int) ((endValue.left - startValue.left) * fraction);
  5. int top = startValue.top + (int) ((endValue.top - startValue.top) * fraction);
  6. int right = startValue.right + (int) ((endValue.right - startValue.right) * fraction);
  7. int bottom = startValue.bottom + (int) ((endValue.bottom - startValue.bottom) * fraction);
  8. if (mRect == null) {
  9. return new Rect(left, top, right, bottom);
  10. } else {
  11. mRect.set(left, top, right, bottom);
  12. return mRect;
  13. }
  14. }
  15. }
2、自定义TypeEvaluator
自定义TypeEvaluator时需要实现evaluate()方法,evaluate()方法中的逻辑基本上可以按下面的公式计算:

startValue+ fraction * (endValue - startValue)

上面的公式只是一种表达形式,要看startValue和endValue 是什么对象,例如RectEvaluator先获取Rect的四个坐标,然后对四个坐标进行数学转换计算。这个fraction关键变量数值由谁决定?这个值由TimeInterpolator时间插值器来决定,TimeInterpolator定义动画的变换速率。下面来看下这个插值器。
二、TimeInterpolator 时间插值器
【Android动画应用---自定义属性动画】1、作用
时间插值器定义动画的变化率,这允许动画具有非线性运动,如加速和减速。这个插值器正决定了上面估值器中的fraction参数值。自定义TimeInterpolator 需要实现float getInterpolation(float input)方法,该方法的返回值决定了fraction。

Android系统中提供的插值器类型有:
  • AccelerateDecelerateInterpolator:其变化率开始和结束缓慢,但通过中间加速;
  • AccelerateInterpolator:其变化率开始缓慢,然后加速;
  • AnticipateInterpolator:开始的时候向后然后向前甩;
  • AnticipateOvershootInterpolator:开始的时候向后,然后向前甩一定值后(超过endvalue)返回到最后的值,弹性回收的感觉;
  • BounceInterpolator:变化在最后时反弹,像皮球落地时的反弹;
  • CycleInterpolator:使用时指定动画循环次数。 变化率遵循正弦模式;
  • DecelerateInterpolator:其变化率开始快速然后减速;
  • LinearInterpolator:变化率以常亮数值变化;
  • OvershootInterpolator:向前甩一定值后再回到原来位置;
  • PathInterpolator:动画变化率和path的坐标有关,path的范围是[0~1]。
Android提供的TimeInterpolator就这些,有兴趣的可以自行查看相关源码,下面分享下CycleInterpolator的实现代码:
需要指定动画循环次数cycles,动画变化率是按正弦函数变化。

[java]view plain copy
  1. public class CycleInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {
  2. public CycleInterpolator(float cycles) {
  3. mCycles = cycles;
  4. }
  5. public CycleInterpolator(Context context, AttributeSet attrs) {
  6. this(context.getResources(), context.getTheme(), attrs);
  7. }
  8. /** @hide */
  9. public CycleInterpolator(Resources resources, Theme theme, AttributeSet attrs) {
  10. TypedArray a;
  11. if (theme != null) {
  12. a = theme.obtainStyledAttributes(attrs, R.styleable.CycleInterpolator, 0, 0);
  13. } else {
  14. a = resources.obtainAttributes(attrs, R.styleable.CycleInterpolator);
  15. }
  16. mCycles = a.getFloat(R.styleable.CycleInterpolator_cycles, 1.0f);
  17. setChangingConfiguration(a.getChangingConfigurations());
  18. a.recycle();
  19. }
  20. public float getInterpolation(float input) {
  21. return (float)(Math.sin(2 * mCycles * Math.PI * input));
  22. }
  23. private float mCycles;
  24. /** @hide */
  25. @Override
  26. public long createNativeInterpolator() {
  27. return NativeInterpolatorFactoryHelper.createCycleInterpolator(mCycles);
  28. }
  29. }
2、自定义TimeInterpolator
自定义TimeInterpolator需要实现float getInterpolation(float input),而这个方法的实现就需要用到你的数学函数知识了,自己可以脑洞打开应用各种函数。下面自己自定义个TimeInterpolator实现先减速后加速:

[java]view plain copy
  1. public class MyInterpolator implements Interpolator {
  2. @Override
  3. public float getInterpolation(float input) {
  4. return ((4*input-2)*(4*input-2)*(4*input-2))/16f + 0.5f;
  5. }
  6. }

自定属性就是自定义并实现上面两个类的相关方法,主要涉及一些数学知识点。望有所帮助~

    推荐阅读