Android动画效果之Property Animation进阶(属性动画)

前言:

     前面初步认识了Android的Property Animation(属性动画)Android动画效果之初识Property Animation(属性动画)(三),而且利用属性动画简单了补间动画可以实现的动画效果,今天重点学习下Property Animation基本原理及高级使用。本章先经过余额宝的数字动画小例子来学习属性动画基本原理。具体效果以下:html

     其余几种动画效果:android

ValueAnimator(差值动画)

    上篇文章一直使用的ObjectAnimator来实现属性动画,单纯从字面上理解的话ObjectAnimator做用于某个实际的对象,而ValueAnimator是ObjectAnimator的父类,它继承自抽象类Animator,它做用于一个值,将其由一个值变化为另一个值,而后根据值的变化,按照必定的规则,动态修改View的属性,好比View的位置、透明度、旋转角度、大小等,便可完成了动画的效果。直接看下上面的数字动画是怎么实现的?设计模式

ValueAnimator valueAnimator =ValueAnimator.ofFloat( 0f, 126512.36f);
valueAnimator.setDuration(2000);
valueAnimator.setInterpolator(new LinearInterpolator());
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
    float money= (float) animation.getAnimatedValue();
    mTextView.setText(String.format("%.2f", money));
    }
});
valueAnimator.start();

这里经过ofFloat()方法构造一个ValueAnimator实例,除此以外还提供了其余函数ofInt()、ofObject()、ofPropertyValuesHolder()函数,api 21以后又提供了ofArgb(),每一个函数都是能够传入多个改变值。api

Interpolator(插值器)

   Interpolator插值器用于控制动画的变化速率,也能够简单的理解成用于控制动画的快慢,插值器目前都只是对动画执行过程的时间进行修饰,并无对轨迹进行修饰。系统提供的插值器有如下几种:ide

插值器名字 解说 对应的xml
AccelerateInterpolator  加速,开始时慢中间加速  @android:anim/accelerate_interpolator
DecelerateInterpolator 减速,开始时快而后减速 @android:anim/decelerate_interpolator
AccelerateDecelerateInterolator   先加速后减速,开始结束时慢,中间加速  @android:anim/accelerate_decelerate_interpolator
AnticipateInterpolator 反向 ,先向相反方向改变一段再加速播放  @android:anim/anticipate_interpolator
AnticipateOvershootInterpolator 反向加超越,先向相反方向改变,再加速播放,会超出目的值而后缓慢移动至目的值 @android:anim/anticipate_overshoot_interpolator
BounceInterpolator  跳跃,快到目的值时值会跳跃,如目的值100,后面的值可能依次为85,77,70,80,90,100 @android:anim/bounce_interpolator
CycleIinterpolator  循环,动画循环必定次数,值的改变为一正弦函数:Math.sin(2* mCycles* Math.PI* input) @android:anim/cycle_interpolator
LinearInterpolator  线性,线性均匀改变 @android:anim/linear_interpolator
OvershootInterpolator 超越,最后超出目的值而后缓慢改变到目的值 @android:anim/overshoot_interpolator

经过上面的名字你们是否是很眼熟,是的和补间动画的插值器是一致的。Android的动画插值器采用策略设计模式,都是实现了Interpolator这个接口,而Interpolator又是继承自一个叫作TimeInterpolator的接口(从3.0开始,增长了TimeInterpolator这个接口,并把原先的Interpolator接口的抽象方法移到了其中,3.0后的Interpolator接口也就什么也没作,只是对父类改了个名字,达到向下兼容)。函数

package android.animation;

public interface TimeInterpolator {

    float getInterpolation(float input);
}

在Interpolator的实现类里面,都实现了一个float getInterpolator(float input)的方法,传入参数是正常执行动画的时间点,返回值是用户真正想要它执行的时间点。上面的数字动画使用了匀速插值器LinearInterpolator其代码实现以下:布局

public class LinearInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {

    public LinearInterpolator() {
    }

    public LinearInterpolator(Context context, AttributeSet attrs) {
    }

    public float getInterpolation(float input) {
        return input;
    }

    /** @hide */
    @Override
    public long createNativeInterpolator() {
        return NativeInterpolatorFactoryHelper.createLinearInterpolator();
    }
}

能够看出float getInterpolator(float input)返回的值就是当前要执行的时间点实现匀速执行动画。post

如何自定义一个插值器?举例:咱们实现一个先减速后加速插值器,代码以下学习

public class DecelerateAccelerateInterpolator implements Interpolator {
    @Override
    public float getInterpolation(float input) {
        float result;
        if (input <= 0.5f) {
            result = (float) (Math.sin(Math.PI * input)) / 2.0f;
        } else {
            result = (float) (2 - Math.sin(Math.PI * input)) / 2.0f;
        }
        return result;
    }
}

TypeEvaluator(估值器)

  TypeEvaluator用于根据当前属性改变的百分比来计算改变后的属性值,系统提供了以下几种估值器字体

  • IntEvaluator 针对整型属性

  • IntArrayEvaluator 针对整型属性集合

  • FloatEvaluator 针对浮点型属性

  • FloatArrayEvaluator 针对浮点型属性集合

  • ArgbEvaluator  针对Color属性

  • RectEvaluator 针对Rect属性

  • PointFEvaluator 针对PointF属性

  TypeEvaluator设计也是采用策略设计模式,都实现TypeEvaluator接口,源代码以下:

package android.animation;

public interface TypeEvaluator<T> {

    public T evaluate(float fraction, T startValue, T endValue);

}

接口提供了evaluate(float fraction, T startValue, T endValue);动画在运行过程当中Interpolator自动计算出动画运行的百分比fraction,而后TypeEvaluator根据fraction计算出当前动画的属性值。以FloatEvaluator 代码为例:

public class FloatEvaluator implements TypeEvaluator<Number> {


    public Float evaluate(float fraction, Number startValue, Number endValue) {
        float startFloat = startValue.floatValue();
        return startFloat + fraction * (endValue.floatValue() - startFloat);
    }
}

 如何自定义TypeEvaLuator?好比咱们要实现一个钱的增长,字体颜色越红的动画,咱们如今都知道可使用ofArgb(),可是ofArgb()须要api 21以上才能使用,因此须要咱们自定义一个ArgbEvaLuator,这里为了演示自定义TypeEvaluator直接把api 21中提供的ArgbEvaluator源代码拿来使用,以下:

public class TextArgbEvaluator implements TypeEvaluator {
    
    public Object evaluate(float fraction, Object startValue, Object endValue) {
        int startInt = (Integer) startValue;
        int startA = (startInt >> 24) & 0xff;
        int startR = (startInt >> 16) & 0xff;
        int startG = (startInt >> 8) & 0xff;
        int startB = startInt & 0xff;

        int endInt = (Integer) endValue;
        int endA = (endInt >> 24) & 0xff;
        int endR = (endInt >> 16) & 0xff;
        int endG = (endInt >> 8) & 0xff;
        int endB = endInt & 0xff;

        return (int) ((startA + (int) (fraction * (endA - startA))) << 24) |
                (int) ((startR + (int) (fraction * (endR - startR))) << 16) |
                (int) ((startG + (int) (fraction * (endG - startG))) << 8) |
                (int) ((startB + (int) (fraction * (endB - startB))));
    }
}

调用方式:

        AnimatorSet animatorSet = new AnimatorSet();
        ValueAnimator valueAnimator = ValueAnimator.ofFloat(0f, 126512.36f);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float money = (float) animation.getAnimatedValue();
                Log.e("Interpolator", "money---->" + money);
                mTextView.setText(String.format("%.2f", money));
            }
        });

        int startColor = Color.parseColor("#FCA3AB");
        int endColor = Color.parseColor("#FB0435");
        ValueAnimator colorAnimator = ValueAnimator.ofObject(new TextArgbEvaluator(),startColor, endColor);
        colorAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                int color = (int) animation.getAnimatedValue();
                Log.e("Interpolator", "color---->" + color);
                mTextView.setTextColor(color);
            }
        });

        animatorSet.playTogether(valueAnimator,colorAnimator);
        animatorSet.setDuration(5000);
        animatorSet.setInterpolator(new LinearInterpolator());
        animatorSet.start();

运行效果:

ObjectAnimator

    上篇咱们简单了学习了ObjectAnimator动画,而且经过ObjectAnimator实现了几种简单的动画效果,ObjectAnimator继承自ValueAnimator,因此主体方法仍是ValueAnimator里实现的。先来回顾一下上篇的一个旋转动画例子。

ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(imageView, "rotation", 0f, 360f);
    objectAnimator.setDuration(500);
    objectAnimator.setRepeatCount(1);
    objectAnimator.setRepeatMode(ValueAnimator.REVERSE);
    objectAnimator.start();

这个例子很简单,针对view的属性rotation进行持续时间为500ms的0到360的角度变换。属性名字rotation在View中有对应setRotation(),不然没有任何效果,并且参数类型必须为float型,不然没有任何效果。view常见可操做的参数有:x/y;scaleX/scaleY;rotationX/ rotationY;transitionX/ transitionY等等。如今问题来了,咱们本篇例子是为TextView 赋值一个float型的值,咱们查看TextView的函数并不找不到setText(float f),这时该怎么处理呢?如何为不具备get/set方法的属性提供修改方法呢?莫着急!谷歌为此提供了两种方法,第一种就是使用ValueAnimator来实现,就是上面所说的方式,另一种方式经过本身写一个包装类,来为该属性提供get/set方法。

public class MoneyTextView extends TextView {
    public MoneyTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public void setText(float money) {
        setText(String.format("%.2f", money));
    }
}

而后就能够经过ObjectAnimator实现上面的数字动画效果了。

 ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(mTextView, "text", 0f, 126512.36f);
    objectAnimator.setDuration(2000);
    objectAnimator.setInterpolator(new LinearInterpolator());
    objectAnimator.start();

其余有关ObjectAnimator的使用方式请参考上篇文章Android动画效果之初识Property Animation(属性动画)(三)

总结:

   本篇主要简单学习了属性动画的基本原理,属性动画使用了比较常见的策略设计模式,感兴趣的话能够看下这篇文章Java设计模式之策略模式(Strategy),下篇文章将借助自定义ViewGroup学习一下布局动画。

相关文章
相关标签/搜索