Android-動畫基礎

屬性動畫-Property Animation

基本流程:

  1. 這個ValueAnimator對象會根據動畫的總時間和已經流逝的時間計算出一個0到1之間的elapsed fraction值。這個elapsed fraction值就代表了時間完成的程度。
  2. 計算出elapsed fraction之後,ValueAnimator對象會調用TimeInterpolator 來計算一個interpolated fraction,即,根據所設置的時間插值方法將elapsed fraction映射到interpolated fraction。
      如果是線性插值的話elapsed fraction和interpolated fraction會是一直相等的,但是非線性變換就不是了。
  3. interpolated fraction計算出來後,ValueAnimator 會調用TypeEvaluator,來進行你要動畫的屬性值的計算。
      這時候用的輸入參數就是interpolated fraction的值,以及屬性值的起始值和終止值。

  整個過程如下圖所示:
  這裏寫圖片描述

View Anim 與 property Anim 的區別

View anim 系統

view animation system 提供的能力只能夠爲 View 添加動畫。因此如果你想爲非 View 對象添加動畫,就必須自己去實現, view animation system 在 View 動畫的展現方面也是有約束的,只暴露了 View 的很少方面。比如 View 支持縮放和旋轉,但不支持背景顏色的動畫。
view animation system 的另一劣勢是,其改變的是 View 的繪製效果,真正的 View 的屬性保持不變,比如無論你在對話中如何縮放 Button 的大小,Button 的有效點擊區域還是沒有應用到動畫時的區域,其位置與大小都不變。
但是 View animation system 只需花費很少時間創建而且只需很少的代碼。如果 View 動畫完成了你所有的動作,或者你存在的代碼已經達到了你想要的效果,就沒必要使用 property 動畫系統了。

property anim 系統

完全彌補了 View anim System 的缺陷,你可以爲一個對象的任何屬性添加動畫,(View 或者非 View),同時對象自己也會被修改。 並且當屬性變化的時候,property Anim 系統會自動的刷新屏幕。
屬性動畫系統在處理動畫方面也更加強勁。更高級的,你可以指定動畫的屬性,比如顏色,位置,大小,定義動畫的插值器並且同步多個動畫。
並且在 Property Animation 中,改變的是對象的實際屬性,如 Button 的縮放,Button 的位置與大小屬性值都改變了。而且 Property Animation 不止可以應用於 View,還可以應用於任何對象。
平時使用的簡單動畫特效,使用 View 動畫就可以滿足,但是如果你想做的更加複雜,比如背景色的動畫,或者不僅是 View,還希望對其它對象添加動畫等,那麼你就得考慮使用 Property 動畫了。
更多動畫開源庫及使用,可以參考:Android 動畫系列,其中介紹了一些基本使用,也提到了一些 GitHub 上的動畫開源庫,可以作爲 Android 動畫學習的資料

1.兩個簡單示例

1.1.ValueAnimator使用

 private static void testValueAnimator() {
        ValueAnimator animator=ValueAnimator.ofFloat(0,100);
        animator.setInterpolator(new LinearInterpolator());
        animator.setDuration(1000);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float fraction = animation.getAnimatedFraction();//時間插值(線性插值器爲0~1)
                float value = (float) animation.getAnimatedValue();//類型估值(0~100)
            }
        });
        animator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(Animator animation) {
                super.onAnimationStart(animation);
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
            }
        });
        animator.start();
    }

1.2.AnimatorSet使用

private static void testAnimatorSet() {
        ValueAnimator animatorA=ValueAnimator.ofFloat(0,1);
        ValueAnimator animatorB=ValueAnimator.ofFloat(0,1);
        ValueAnimator animatorC=ValueAnimator.ofFloat(0,1);
        ValueAnimator animatorD=ValueAnimator.ofFloat(0,1);

        //A、B、C同時執行,D接着執行
        AnimatorSet animSet = new AnimatorSet();
        animSet.play(animatorA).with(animatorB);
        animSet.play(animatorB).with(animatorC);
        animSet.play(animatorD).after(animatorC);
        animSet.setDuration(1000);
        animSet.start();
    }

2.Android自帶時間插值器

Interpolator 被用來修飾動畫效果,定義動畫的變化率,可以使存在的動畫效果accelerated(加速),decelerated(減速),repeated(重複),bounced(彈跳)等。

2.1.Linear Interpolator / 線性插值器

類名: LinearInterpolator
資源ID: @android:anim/linear_interpolator
XML標記: linearInterpolator
公式: y=t
構造函數: public LinearInterpolator()
屬性: 無

這裏寫圖片描述

2.2.Accelerate Interpolator / 加速度插值器

類名: AccelerateInterpolator
資源ID: @android:anim/accelerate_interpolator
XML標記: accelerateInterpolator
公式: y=t^(2f)
構造函數: public AccelerateInterpolator(float factor)
參數:
名稱: f
XML屬性: android:factor
描述: 加速度參數. f越大,起始速度越慢,但是速度越來越快

![這裏寫圖片描述](http://s3.51cto.com/wyfs02/M02/2F/4D/wKioL1OfBg7RSunbAAEfeaz5sDM514.jpg)

2.3.Decelerate Interpolator / 減速插值器

類名: DecelerateInterpolator
資源ID: @android:anim/decelerate_interpolator
XML標記: decelerateInterpolator
公式: y=1-(1-t)^(2f)
構造函數: public DecelerateInterpolator(float factor)
參數:
名稱: f
XML屬性: android:factor
描述: 加速度參數. f越大,起始速度越快,但是速度越來越慢

這裏寫圖片描述

2.4.Accelerate Decelerate Interpolator / 先加速後減速插值器

類名: AccelerateDecelerateInterpolator
資源ID: @android:anim/accelerate_decelerate_interpolator
XML標記: accelerateDecelerateInterpolator
公式: y=cos((t+1)π)/2+0.5
構造函數: public AccelerateDecelerateInterpolator()
參數: 無

這裏寫圖片描述

2.5.Anticipate Interpolator

類名: AnticipateInterpolator
資源ID: @android:anim/anticipate_interpolator
XML標記: anticipateInterpolator
公式: y=(T+1)×t^3–T×t^2
構造函數: public AnticipateInterpolator(float tension)
參數:
名稱: T
XML屬性: android:tension
描述: 張力值, 默認爲2,T越大,初始的偏移越大,而且速度越快

這裏寫圖片描述

2.6.Overshoot Interpolator

類名: OvershootInterpolator
資源ID: @android:anim/overshoot_interpolator
XML標記: overshootInterpolator
公式: y=(T+1)x(t1)^3+T×(t1)^2 +1
構造函數: public OvershootInterpolator (float tension)
參數:
名稱: T
XML屬性: android:tension
描述: 張力值,默認爲2,T越大,結束時的偏移越大,而且速度越快

這裏寫圖片描述

2.7.Anticipate Overshoot Interpolator

類名: AnticipateOvershootInterpolator
資源ID: @android:anim/anticipate_overshoot_interpolator
XML標記: anticipateOvershootInterpolator
公式:
這裏寫圖片描述
構造函數:
public AnticipateOvershootInterpolator(float tension)
public AnticipateOvershootInterpolator(float tension, float extraTension)
參數:
XML屬性: android:tension
描述: 張力值,默認爲2,張力越大,起始和結束時的偏移越大,而且速度越快
XML屬性: android:extraTension
描述: 額外張力值,默認爲1.5。公式中T的值爲tension*extraTension

這裏寫圖片描述

2.8.Bounce Interpolator / 彈跳插值器

類名: BounceInterpolator
資源ID: @android:anim/bounce_interpolator
XML標記: bounceInterpolator
公式:
這裏寫圖片描述
構造函數: public BounceInterpolator ()
參數: 無

這裏寫圖片描述

2.9.Cycle Interpolator / 週期插值器

類名: CycleInterpolator
資源ID: @android:anim/cycle_interpolator
XML標記: cycleInterpolator
公式: y=sin(2π×C×t)
構造函數: public CycleInterpolator(float cycles)
參數:
名稱: C
XML屬性: android:cycles
描述: 週期值,默認爲1;2表示動畫會執行兩次

這裏寫圖片描述

自定義Interpolator與TypeEvaluator

1.思路:

  1. 自定義Interpolator需要重寫getInterpolation(float input),控制時間參數的變化;
  2. 自定義TypeEvaluator需要重寫evaluate()方法,計算對象的屬性值並將其封裝成一個新對象返回;

2.自定義插值器

下面,我們就來創建自己的Interpolator。上面已經講得非常清楚了,Interpolator的關鍵在於公式。我想創建的Interpolator名字叫HesitateInterPolator:起始時速度全速,快到一半時減速到0,然後加速直到終點,
用圖形來表示即:
這裏寫圖片描述
用數學公式來表示即:
這裏寫圖片描述
我們只需要實現Interpolator接口,然後實現其中的float getInterpolation(float t)接口即可:

public class HesitateInterpolator implements Interpolator {
    public HesitateInterpolator() {}
    public float getInterpolation(float t) {
      float x=2.0f*t-1.0f;
      return 0.5f*(x*x*x + 1.0f);
    }
}

3.自定義類型估值

public class ColorEvaluator implements TypeEvaluator {  

    private int mCurrentRed = -1;  

    private int mCurrentGreen = -1;  

    private int mCurrentBlue = -1;  

    @Override  
    public Object evaluate(float fraction, Object startValue, Object endValue) {  
        String startColor = (String) startValue;  
        String endColor = (String) endValue;  
        int startRed = Integer.parseInt(startColor.substring(1, 3), 16);  
        int startGreen = Integer.parseInt(startColor.substring(3, 5), 16);  
        int startBlue = Integer.parseInt(startColor.substring(5, 7), 16);  
        int endRed = Integer.parseInt(endColor.substring(1, 3), 16);  
        int endGreen = Integer.parseInt(endColor.substring(3, 5), 16);  
        int endBlue = Integer.parseInt(endColor.substring(5, 7), 16);  
        // 初始化顏色的值  
        if (mCurrentRed == -1) {  
            mCurrentRed = startRed;  
        }  
        if (mCurrentGreen == -1) {  
            mCurrentGreen = startGreen;  
        }  
        if (mCurrentBlue == -1) {  
            mCurrentBlue = startBlue;  
        }  
        // 計算初始顏色和結束顏色之間的差值  
        int redDiff = Math.abs(startRed - endRed);  
        int greenDiff = Math.abs(startGreen - endGreen);  
        int blueDiff = Math.abs(startBlue - endBlue);  
        int colorDiff = redDiff + greenDiff + blueDiff;  
        if (mCurrentRed != endRed) {  
            mCurrentRed = getCurrentColor(startRed, endRed, colorDiff, 0,  
                    fraction);  
        } else if (mCurrentGreen != endGreen) {  
            mCurrentGreen = getCurrentColor(startGreen, endGreen, colorDiff,  
                    redDiff, fraction);  
        } else if (mCurrentBlue != endBlue) {  
            mCurrentBlue = getCurrentColor(startBlue, endBlue, colorDiff,  
                    redDiff + greenDiff, fraction);  
        }  
        // 將計算出的當前顏色的值組裝返回  
        String currentColor = "#" + getHexString(mCurrentRed)  
                + getHexString(mCurrentGreen) + getHexString(mCurrentBlue);  
        return currentColor;  
    }  

    /** 
     * 根據fraction值來計算當前的顏色。 
     */  
    private int getCurrentColor(int startColor, int endColor, int colorDiff,  
            int offset, float fraction) {  
        int currentColor;  
        if (startColor > endColor) {  
            currentColor = (int) (startColor - (fraction * colorDiff - offset));  
            if (currentColor < endColor) {  
                currentColor = endColor;  
            }  
        } else {  
            currentColor = (int) (startColor + (fraction * colorDiff - offset));  
            if (currentColor > endColor) {  
                currentColor = endColor;  
            }  
        }  
        return currentColor;  
    }  

    /** 
     * 將10進制顏色值轉換成16進制。 
     */  
    private String getHexString(int value) {  
        String hexString = Integer.toHexString(value);  
        if (hexString.length() == 1) {  
            hexString = "0" + hexString;  
        }  
        return hexString;  
    }  

}  

參考目錄:
1. Interpolators詳解
2. 公共技術點之Android動畫基礎
3. Android動畫系列

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章