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學習一下佈局動畫。

相關文章
相關標籤/搜索