Android動畫解析 View動畫,幀動畫與屬性動畫

Android的動畫形式共分爲三種,View動畫,幀動畫與屬性動畫。

先對這三種動畫做一個概述:

View動畫是一種漸進式動畫,通過圖像的平移、縮放、旋轉和透明度等各種漸進式變換完成動畫效果。

幀動畫是通過不停的切換圖片實現動畫效果。

屬性動畫是不停的改變對象的屬性來實現動畫效果。


View動畫:

Android系統提供的View動畫分爲四類,RotateAnimation,ScaleAnimation,TranslateAnimation,AlphaAnimation,此外,Android還提供了AnimationSet,將四種動畫進行組合使用。View動畫可以通過setDuration方法,setInterpolator方法,setAnimationListener和setFillAfter方法來設置動畫運行的時長,動畫的播放速度,對動畫進行監聽和動畫運行結束後View的狀態。

View動畫還可以爲ViewGroup和Activity設置動畫。


幀動畫:

幀動畫就是不停的切換圖片來實現動畫效果,就如同小人書,但比較容易出現OOM,所以在使用時,需要注意圖片大小。


屬性動畫:

View動畫的那四種效果有很明顯的缺點,繪製出來的效果其實並沒有真正改變View的屬性,即left、top、right和bottom的值,只是系統臨時繪製的結果。這樣View的點擊位置並沒有發生變化。針對這個問題,從Android3.0開始屬性動畫應運而生。

屬性動畫本質是通過改變新增的屬性(如平移translationX/Y、縮放scaleX/Y、旋轉rotationX/Y等)並刷新屏幕來實現動畫效果,並且實現點擊位置的實時改變。但是屬性動畫仍然不會修改原始的上下左右四個值。最後需要注意的是,屬性動畫不止用於View,還可以用於任何對象。

ValueAnimator是整個屬性動畫機制中最核心的一個類,屬性動畫的運行機制是通過不斷地對值進行操作來實現的,而初始值和結束值之間的動畫過渡就是由ValueAnimator類來負責計算的。它的內部使用一種時間循環的機制來計算值與值之間的動畫過渡,我們只需要將初始值和結束值提供給ValueAnimator,並且告訴它動畫所需運行的時長,那麼ValueAnimator就會自動幫我們完成從初始值平滑地過渡到結束值這樣的效果。除此之外,ValueAnimator還負責管理動畫的播放次數、播放模式、以及對動畫設置監聽器等,確實是一個非常重要的類。


ObjectAnimator是我們最常接觸的類,它繼承自ValueAnimator。由於ValueAnimator只是對值進行了一個平滑的動畫過渡,我們在實際中應用的場景並不多。而ObjectAnimator就不同了,它可以直接對任意對象的任意屬性進行動畫操作,例如 alpha, rotation, translationX, translationY, scaleX, scaleY等。我們同樣可以使用AnimationSet來將不同屬性的動畫進行組合。

Animator監聽器

Animator類中提供了addListener方法來對屬性動畫進行監聽,這個方法接收一個AnimationListener,我們只需要實現AnimationListener就可以監聽動畫的各種事件了。我們已經知道了ObjectAnimator繼承自ValueAnimator,而ValueAnimator又繼承自Animator,因此,ObjectAnimator與ValueAnimator都可以使用addListener方法來對動畫進行監聽。

    anim.addListener(new AnimatorListener() {  
        @Override  
        public void onAnimationStart(Animator animation) {  
        }  
      
        @Override  
        public void onAnimationRepeat(Animator animation) {  
        }  
      
        @Override  
        public void onAnimationEnd(Animator animation) {  
        }  
      
        @Override  
        public void onAnimationCancel(Animator animation) {  
        }  
    });  

但有時候我們並不會使用AnimationListener中的所有方法,這就會造成出現很多空方法的狀況。這種情況下,我們可以使用AnimationListenerAdapter,裏面已經定義了每個方法的空方法,我們只需要重寫我們需要的方法就可以了。


Animator類還可添加更新監聽器,如下,

valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                Point point = (Point)animation.getAnimatedValue();
                circle.x = point.getX();
                circle.y = point.getY();
                circle.invalidate();
            }
        })

在AnimatorUpdateListener接口中的onAnimationUpdate方法中,調用animation.getAnimatedValue()方法即可獲得Animator更新後的最新屬性(ObjectAnimator)或值(ValueAnimator)。


插值器TimeInterpolator與估值器TypeEvaluator

public interface TimeInterpolator {

    /**
     * Maps a value representing the elapsed fraction of an animation to a value that represents
     * the interpolated fraction. This interpolated value is then multiplied by the change in
     * value of an animation to derive the animated value at the current elapsed animation time.
     *
     * @param input A value between 0 and 1.0 indicating our current point
     *        in the animation where 0 represents the start and 1.0 represents
     *        the end
     * @return The interpolation value. This value can be more than 1.0 for
     *         interpolators which overshoot their targets, or less than 0 for
     *         interpolators that undershoot their targets.
     */
    float getInterpolation(float input);
}

public interface TypeEvaluator<T> {

    /**
     * This function returns the result of linearly interpolating the start and end values, with
     * <code>fraction</code> representing the proportion between the start and end values. The
     * calculation is a simple parametric calculation: <code>result = x0 + t * (x1 - x0)</code>,
     * where <code>x0</code> is <code>startValue</code>, <code>x1</code> is <code>endValue</code>,
     * and <code>t</code> is <code>fraction</code>.
     *
     * @param fraction   The fraction from the starting to the ending values
     * @param startValue The start value.
     * @param endValue   The end value.
     * @return A linear interpolation between the start and end values, given the
     *         <code>fraction</code> parameter.
     */
    public T evaluate(float fraction, T startValue, T endValue);

}

插值器TimeInterpolator是用來控制動畫的節奏快慢的,估值器TypeEvaluator是用來控制動畫的實現的。


TimeInterpolator接口中的getInterpolation方法接收一個float變量input,input的取值範圍爲0~1,表示當前運行了的時間在設定時間中的位置,返回值即爲TypeEvaluator接口中evaluate方法中的參數fraction。evaluate方法根據傳入的fraction,起始值startValue,結束值endValue來控制動畫。ofFloat與ofInt默認使用FloatEvaluator類和IntEvaluator類。

public class FloatEvaluator implements TypeEvaluator<Number> {

    /**
     * This function returns the result of linearly interpolating the start and end values, with
     * <code>fraction</code> representing the proportion between the start and end values. The
     * calculation is a simple parametric calculation: <code>result = x0 + t * (v1 - v0)</code>,
     * where <code>x0</code> is <code>startValue</code>, <code>x1</code> is <code>endValue</code>,
     * and <code>t</code> is <code>fraction</code>.
     *
     * @param fraction   The fraction from the starting to the ending values
     * @param startValue The start value; should be of type <code>float</code> or
     *                   <code>Float</code>
     * @param endValue   The end value; should be of type <code>float</code> or <code>Float</code>
     * @return A linear interpolation between the start and end values, given the
     *         <code>fraction</code> parameter.
     */
    public Float evaluate(float fraction, Number startValue, Number endValue) {
        float startFloat = startValue.floatValue();
        return startFloat + fraction * (endValue.floatValue() - startFloat);
    }
}

public class IntEvaluator implements TypeEvaluator<Integer> {

    /**
     * This function returns the result of linearly interpolating the start and end values, with
     * <code>fraction</code> representing the proportion between the start and end values. The
     * calculation is a simple parametric calculation: <code>result = x0 + t * (v1 - v0)</code>,
     * where <code>x0</code> is <code>startValue</code>, <code>x1</code> is <code>endValue</code>,
     * and <code>t</code> is <code>fraction</code>.
     *
     * @param fraction   The fraction from the starting to the ending values
     * @param startValue The start value; should be of type <code>int</code> or
     *                   <code>Integer</code>
     * @param endValue   The end value; should be of type <code>int</code> or <code>Integer</code>
     * @return A linear interpolation between the start and end values, given the
     *         <code>fraction</code> parameter.
     */
    public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
        int startInt = startValue;
        return (int)(startInt + fraction * (endValue - startInt));
    }
}

從上面FloatEvaluator和IntEvaluator的evaluator方法,我們可以很清晰的看出,只是將簡單的計算了startValue與endValue中間的fraction處的值返回即可。

如果是ofObject方法,則需要自己定義TypeEvaluator,只需實現TimeInterpolator接口即可。

如果不自定義TimeInterpolator,默認getInterpolation方法默認直接返回input。我們可以使用setInterpolator方法設置自定義的TimeInterpolator。根據input計算不同的fraction,便可控制動畫運行的速率變化。


好了,屬性動畫就是這麼簡單,你學會了嗎?

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