天天看點

android 動畫詳解之屬性動畫

動畫的分類

在android3.0以前,android的動畫機制比較簡單,也可以說不健全,那時候是分為兩種實作方式:幀動畫和補間動畫。

1. 幀動畫說白了就像gif,在實作的過程中依賴一幀幀的圖檔資源,然後加載輪播

2. 補間動畫倒是可以對view做一些簡單的動态效果,但是功能過于簡陋,隻能夠實作移動、縮放、旋轉和淡入淡出這四種動畫操作,局限性很大。

在3.0之後android提供了一個更加全面和強大的動畫實作方式:屬性動畫。基于此我們可以實作各種各樣的動畫效果。當然前提你得會用….

一、屬性動畫的實作原理

屬性動畫的實作原理其實就是通過對值的不斷操作。基于這個實作機制我們就可以在view的外層或内部對view進行持續性的更改操作已完成動畫的效果。舉個栗子吧:通過以下動畫使button的透明度在3秒内從0勻速增至1

ValueAnimator valueAnimator =  ValueAnimator.ofFloat(f,f);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
             button.setAlpha((float)animation.getAnimatedValue());
            }
        });
        valueAnimator.setDuration();
        valueAnimator.start();
           

當然我們也可以通過setInterpolator()來設定值遞增的加速度。

二、ObjectAnimator

ObjectAnimator是ValueAnimator的子類,也是我們用的比較多的個動畫實作類。通過ObjectAnimator我們可以快速的實作上述效果:

ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(button, "alpha",f,f);
objectAnimator.setDuration();
objectAnimator.start();
           

這裡就表示在3000毫秒内對button的alpha屬性進行操作,使其值從0遞增到1,進而實作button的透明值漸變動畫。這裡”alpha”表示對button的alpha屬性進行操作,我們還可以傳入”rotation”,”translationX”,”translationY”對view的旋轉和位移進行動畫表示。

三、組合動畫

有時候單一的屬性并不足以支撐我們的動畫效果,這時候就需要使用組合動畫,組合動畫通過AnimatorSet将多個ObjectAnimator動畫組合成一個動畫集合進行展示。

// 使按鈕從左側進入
        ObjectAnimator moveIn = ObjectAnimator.ofFloat(button, "translationX", -, );
        moveIn.setDuration();

        // 使按鈕變為透明,再還原
        ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(button, "alpha",,,);
        alphaAnimator.setDuration();

        // 使按鈕旋轉360°
        ObjectAnimator rotationAnimator = ObjectAnimator.ofFloat(button, "rotation", , );
        rotationAnimator.setDuration();

        // 組合上面三個動畫
        AnimatorSet animators = new AnimatorSet();
        animators.play(alphaAnimator).with(rotationAnimator).after(moveIn);
        animators.start();
           

animatorSet有4個方法用以實作動畫的組合邏輯,分别是:

1. after(Animator anim) 将現有動畫插入到傳入的動畫之後執行

2. after(long delay) 将現有動畫延遲指定毫秒後執行

3. before(Animator anim) 将現有動畫插入到傳入的動畫之前執行

4. with(Animator anim) 将現有動畫和傳入的動畫同時執行

after\before\with不光可以傳入單一的屬性動畫, 也可以傳入AnimatorSet組合動畫。這樣我們就能組合出特殊效果的動畫了。

// 垂直方向縮放大小
        ObjectAnimator scaleYAnimator = ObjectAnimator.ofFloat(button,"scaleY",,,);
        scaleYAnimator.setDuration();

        // 組合animators動畫集合和scaleYAnaimator
        AnimatorSet animatorSet = new AnimatorSet();
        animatorSet.play(animatorSet).with(scaleYAnimator);
        animatorSet.start();
           

四、動畫監聽

我們還可以監聽動畫在不同的節點的事件并執行相應的處理,比如開始動畫、結束動畫。Animator總共提供了4個監聽事件如下:

animatorSet.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) {  
    }  
});  
           

ObjectAnimator和AnimatorSet都是繼承自Animator,是以他們都有AnimatorListener監聽接口。很多時候我們并不會監聽所有的事件,可能隻會單獨監聽開始事件或者結束事件,我們可在這裡傳入實作了AnimatorListener的抽象類AnimatorListAdapter,然後選擇性的實作AnimatorListener的某個或者多個事件。如下:

animator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                // do anything
            }
        });
           

五、Interpolator插值器

Interpolator主要是用來控制動畫的變化率的,打個比方說,自由落體運動,剛開始下落的速度為0,但是由于重力加速度導緻其下落速度逐漸增大。Interpolator的作用就相當于重力加速度。現有系統提供了以下幾種插值器:

1. LinearInterpolator(線性插值器):勻速動畫。 

2. AccelerateDecelerateInterpolator(加速減速插值器):動畫兩頭慢,中間快。 

3. DecelerateInterpolator(減速插值器):動畫越來越慢。

4. BounceInterpolator(彈跳插值器):先加速至指向位置,然後反彈數次,逐漸停留至預定目标值。

5. CycleInterpolator(周期插值器):重複動畫數次,依照正弦曲線的頻率執行。

6. OvershootInterpolator:加速執行,會超出預定目标值,最火回至預定目标值。

7. AnticipateInterpolator:先反向執行,然後加速正向執行至目标值。

8. AnticipateOvershootInterpolator:先反向執行,然後加速正向執行, 會超出預定目标值,最後回至預定目标值。
           

動畫未設定或者傳入插值器為空,則預設采用LinearInterpolator插值器。

六、XML編寫動畫

我們就以最後一個組合的動畫為例,采用xml進行編寫實作。

xml代碼如下:

<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:ordering="sequentially" >
    <!--從左側平移進入-->
    <objectAnimator
        android:duration="2000"
        android:propertyName="translationX"
        android:valueFrom="-500"
        android:valueTo="0"
        android:valueType="floatType" >
    </objectAnimator>

    <set android:ordering="together" >
        <!--旋轉360度-->
        <objectAnimator
            android:duration="3000"
            android:propertyName="rotation"
            android:valueFrom="0"
            android:valueTo="360"
            android:valueType="floatType" >
        </objectAnimator>

        <set android:ordering="sequentially">
            <!--變透明,再還原-->
            <objectAnimator
                android:duration="1500"
                android:propertyName="alpha"
                android:valueFrom="1"
                android:valueTo="0"
                android:valueType="floatType" >
            </objectAnimator>
            <objectAnimator
                android:duration="1500"
                android:propertyName="alpha"
                android:valueFrom="0"
                android:valueTo="1"
                android:valueType="floatType" >
            </objectAnimator>
        </set>

    </set>
    <!--垂直方向放大,再還原-->
    <objectAnimator
        android:duration="1500"
        android:propertyName="scaleY"
        android:valueFrom="1"
        android:valueTo="3"
        android:valueType="floatType" >
    </objectAnimator>

    <objectAnimator
        android:duration="1500"
        android:propertyName="scaleY"
        android:valueFrom="3"
        android:valueTo="1"
        android:valueType="floatType" >
    </objectAnimator>
</set>
           
  1. 節點

    xml檔案裡共用了兩個節點,分别是set、objectAnimator分别對應代碼裡的AnimatorSet和ObjectAnimator。那麼他們的屬性也就一目了然了。其中不一樣的是xml配置的動畫執行邏輯。

  2. 屬性配置

    在代碼裡我們可通過with/after/before來配置其執行次序,但在xml裡的先後順序則是根據代碼的先後順序确定的,,也就是說xml裡隻有兩種順序關系,先後和同時。android:ordering=”sequentially”表示順序執行,android:ordering=”together”表示同時執行。其他屬性則可對應代碼裡設定方法。