1. 程式人生 > >屬性動畫:基本使用和組合動畫

屬性動畫:基本使用和組合動畫

今天道長說一下屬性動畫。畢竟現在手機app上基本上都會有動畫的存在,像一些介面的切換,載入等等。屬性動畫是在Android3.0引入的,在此之前,幀動畫和補間動畫一起雄霸天下,那時的動畫還不怎麼複雜和炫酷,直到屬性動畫的出現讓一些瘋狂的產品經理在app中大量的新增動畫甚至組合動畫的需求……

一、三種動畫

幀動畫(frame-by-frame animation):顧名思義就是將一個完整的動畫拆分成一張張單獨的圖片,然後再將它們連貫起來進行播放,類似於動畫片的工作原理。
補間動畫(tweened animation):則是可以對View進行一系列的動畫操作,包括淡入淡出、縮放、平移、旋轉四種。

  • 補間動畫有兩個缺陷:
    1.補間動畫只能夠作用在承自View的元件上的,不可對非View的物件進行操作。
    2.補間動畫不對控制元件原有屬性改變,也就是說View的淡入淡出、縮放、平移、旋轉四種動畫執行完,該View的位置,顏色,大小等等屬性都沒有改變。

屬性動畫(property animation):功能非常強大,彌補了之前補間動畫的一些缺陷,幾乎是可以完全替代掉補間動畫

二、屬性動畫

補間動畫和幀動畫的出現比較早了,有很多功能的實現都已經被屬性動畫替代,這裡道長就不過多講關於補間動畫和幀動畫的內容了。

1.ObjectAnimator

對一個View進行動畫操作,ObjectAnimator是我們最常接觸到的類,可以直接對任意物件的任意屬性進行動畫操作

  • 透明度
    TextView在5秒內從常規變換成全透明,再從全透明變換成常規:
ObjectAnimator animator = ObjectAnimator.ofFloat(textview, "alpha", 1f, 0f, 1f); 
animator.setDuration(5000); 
animator.start();
  • 旋轉
    TextView在5秒內進行一次360度的旋轉:
ObjectAnimator animator = ObjectAnimator.ofFloat(textview, "rotation", 0f, 360f); 
animator.setDuration
(5000); animator.start();
  • 平移
    TextView在5秒內先向左移出螢幕,然後再移動回來:
float curTranslationX = textview.getTranslationX(); 
ObjectAnimator animator = ObjectAnimator.ofFloat(textview, "translationX", curTranslationX, -500f, curTranslationX); 
animator.setDuration(5000); 
animator.start();

這裡道長呼叫了TextView的getTranslationX()方法來獲取到當前TextView的translationX的位置,然後ofFloat()方法的第二個引數傳入”translationX”告訴TextView要水平移動,緊接著後面三個引數用於告訴系統TextView應該怎麼移動

  • 縮放
    TextView5秒內在垂直方向上放大3倍再還原,就可以這樣寫:
ObjectAnimator animator = ObjectAnimator.ofFloat(textview, "scaleY", 1f, 3f, 1f); 
animator.setDuration(5000); 
animator.start();

ObjectAnimator中的常用方法:

  • setStartDelay() - 設定動畫延遲播放的時間
  • setRepeatCount() - 設定動畫迴圈播放的次數
  • setRepeatMode() - 設定動畫迴圈播放的模式,迴圈模式包括RESTART和REVERSE兩種,分別表示重新播放和倒序播放。

2.XML編寫動畫

除了使用程式碼動態編寫動畫外還可以使用xml編寫動畫,使用xml編寫的動畫複用率比較高,可以大大減少app的體量,當然有利有弊,使用xml編寫動畫要比程式碼編寫要慢,而且沒有程式碼編寫靈活。
要使用xml編寫動畫,首先要在res目錄下面新建一個anim資料夾,所有屬性動畫的XML檔案都應該存放在這個資料夾當中。然後在XML檔案中我們一共可以使用如下三種標籤:

  <animator> - 對應程式碼中的ValueAnimator
  <objectAnimator> - 對應程式碼中的ObjectAnimator
  <set> - 對應程式碼中的AnimatorSet

假如要實現一個從0到100平滑過渡的動畫,在XML當中就可以這樣寫:

<animator xmlns:android="http://schemas.android.com/apk/res/android" 
    android:valueFrom="0" 
    android:valueTo="100" 
    android:valueType="intType"/>

如果將一個檢視的alpha屬性從1變成0,就可以這樣寫:

<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" 
    android:valueFrom="1" 
    android:valueTo="0" 
    android:valueType="floatType" 
    android:propertyName="alpha"/>

也可以這樣寫:

<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="300"
    android:fromAlpha="1.0"
    android:interpolator="@android:anim/accelerate_interpolator"
    android:toAlpha="0.0" />

還可以這樣寫:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >

<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="300"
    android:fromAlpha="1.0"
    android:interpolator="@android:anim/accelerate_interpolator"
    android:toAlpha="0.0" />

</set>

然後在程式碼中呼叫即可:

Animator animator = AnimatorInflater.loadAnimator(context, R.animator.anim); 
animator.setTarget(view); 
animator.start();

3.呼叫View的方法編寫動畫

雖然TextView中沒有alpha之類的屬性,但是 ObjectAnimator內部的工作機制並不是直接對我們傳入的屬性名進行操作的,而是會去尋找這個屬性名對應的get和set方法。所以我們也可以使用api編寫動畫。

        view.setRotation(360*fraction);//設定旋轉的角度
//      view.setRotationX(360*fraction);//設定圍繞x軸旋轉的角度
//      view.setRotationY(360*fraction);//設定圍繞Y軸旋轉的角度

4.呼叫NineOldAndroid的方法編寫動畫

屬性動畫是Android3.0引入的,如果在Android3.0之前的系統上想要使用屬性動畫就要使用NineOldAndroid將3.0之後的屬性動畫和view相關的方法相容到了3.0之前。

//      使用NineOldAndroid中的方法
//      ViewHelper.setRotation(redView, 360*fraction);//設定旋轉的角度
        ViewHelper.setScaleX(redView, 1+fraction*0.5f);
        ViewHelper.setScaleY(redView, 1+fraction*0.5f);

總之實現的方法還是比較多的。

三、組合動畫

1.程式碼編寫

上面的就是屬性動畫獨立執行的程式碼,但是獨立的動畫能夠實現的視覺效果畢竟是相當有限的,因此將多個動畫組合到一起播放就顯得尤為重要。實現組合動畫功能主要需要藉助AnimatorSet這個類以及其中的四個方法:

  • after(Animator anim) - 將現有動畫插入到傳入的動畫之後執行
  • after(long delay) - 將現有動畫延遲指定毫秒後執行
  • before(Animator anim) - 將現有動畫插入到傳入的動畫之前執行
  • with(Animator anim) - 將現有動畫和傳入的動畫同時執行

有了這四個方法,就可以讓我們的動畫按照邏輯執行了,比如說我們想要讓TextView先從螢幕外移動進螢幕,然後開始旋轉360度,旋轉的同時進行淡入淡出操作,就可以這樣寫:

ObjectAnimator moveIn = ObjectAnimator.ofFloat(textview, "translationX", -500f, 0f); 
ObjectAnimator rotate = ObjectAnimator.ofFloat(textview, "rotation", 0f, 360f); 
ObjectAnimator fadeInOut = ObjectAnimator.ofFloat(textview, "alpha", 1f, 0f, 1f); 
AnimatorSet animSet = new AnimatorSet(); 
animSet.play(rotate).with(fadeInOut).after(moveIn); 
animSet.setDuration(5000); 
animSet.start();

這是一種比較常見的用法,我們也可以這麼使用:

public void propertyValuesHolder(View view) {
    PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("alpha", 1f, 0f, 1f);
    PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("scaleX", 1f, 0, 1f);
    PropertyValuesHolder pvhZ = PropertyValuesHolder.ofFloat("scaleY", 1f, 0, 1f);
    ObjectAnimator.ofPropertyValuesHolder(view, pvhX, pvhY, pvhZ).setDuration(1000).start();
}

2.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" > 
        <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> 
</set>

選擇使用程式碼編寫還是使用xml編寫主要看需求了,如果產品需求的複用可能性比較大就用xml,其他的看心情。

四、Animator監聽器

一般在動畫執行的時候或者動畫執行完要去執行邏輯程式碼,這時候我們就希望可以監聽到動畫的各種事件,比如動畫何時開始,何時結束。
我們可以新增一個監聽器來實現監聽,如下所示:

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

監聽接口裡的這四個方法就不多說了,如果不想每次都重寫這四個方法還可以實現監聽介面卡這個類,程式碼如下:

anim.addListener(new AnimatorListenerAdapter() { 
    @Override 
    public void onAnimationEnd(Animator animation) { 
    } 
});

屬性動畫的基本使用和組合動畫就說到這裡,一般的需求也就用到這麼多,下次道長在說一下屬性動畫的高階應用。希望這篇部落格能為你提供一些幫助。