Property Animation Part II(屬性動畫 第二部分)

如何使用ValueAnimator

ValueAnimator類通過指定一組整數,浮點數,或色彩值,以及動畫的持續時間來定義。獲得一個ValueAnimator對象的實例需要調用它的一個工廠方法:ofint(),offloat() ,或者ofobject(),如下所示:

ValueAnimator animation = ValueAnimator.ofFloat(0f, 1f);
animation.setDuration(1000);
animation.start();

在這段代碼中,當start()方法開始運行時,ValueAnimator開始計算在0f和1f之間動畫的值,動畫的持續時間爲1000毫秒。
你也可以指定一個自定義類型的動畫如下所示:

ValueAnimator animation = ValueAnimator.ofObject(new MyTypeEvaluator(), startPropertyValue, endPropertyValue);
animation.setDuration(1000);
animation.start();

在這段代碼中,當start()方法開始運行時,ValueAnimator開始根據MyTypeEvaluator計算在startpropertyvalue和endpropertyvalue的值,動畫的持續時間爲1000毫秒。

上面的代碼片段,對於某個對象來說,並沒有實際的效果,因爲ValueAnimator類並不直接對象或屬性產生影響。你所需要做的是根據計算得到的值來改變對象的某些屬性。你可以通過監聽ValueAnimator在動畫生命週期中的接口來處理邏輯,比如幀更新。在實現接口時,你可以通過調用getAnimatedValue()來得到特定幀的計算值。

如何使用ObjectAnimator

ObjectAnimator是ValueAnimator的子類,該類會根據計算所得到的數值來直接對預先指定的對象的屬性進行更改,由於ObjectAnimator已經自動實現了ValueAnimator.AnimatorUpdateListener,不再需要你來實現 ,這使得對一個對象添加動畫變得簡單了許多。

實例化一個ObjectAnimator類同上面很相似,但是你需要指定對象和該對象的屬性的名稱(一個字符串),該屬性的值會在動畫過程中發生變化,簡單的示例如下:

ObjectAnimator anim = ObjectAnimator.ofFloat(foo, "alpha", 0f, 1f);
anim.setDuration(1000);
anim.start();

爲了使得ObjectAnimator可以正確的更新屬性,你必須做到以下幾點

  • 隨着動畫發生變化的對象屬性必須有一個setter方法(駱駝命名規則)。因爲ObjectAnimator動畫自動更新屬性時,它必須能夠通過setter方法訪問該屬性。例如,如果屬性名爲foo,你需要有一個setfoo()方法。如果這個setter方法不存在,你有三個選擇:

    • 在對應的類中添加setter方法

    • 使用一個封裝類,封裝類中定義一個setter方法,該方法可以將值傳遞給你想要改變的那個屬性

    • 使用ValueAnimator類來實現

  • 如果在初始化時,你只指定了一個值,那麼該值會被認爲是動畫的結束值。因此,在你的動畫對象屬性中必須有一個getter函數用於獲取動畫的起始值。例如,如果屬性名爲foo,你需要有一個getfoo()方法。

  • 在ObjectAnimator中,屬性的getter方法(如果有必要)和setter方法同你指定的的開始和結束值的數據類型必須相同。在下面的示例中,你的targetObject就必須有targetObject.setPropName(float) 和 targetObject.getPropName(float) 方法

ObjectAnimator.ofFloat(targetObject, "propName", 1f);
  • 當你改變某些對象的某些屬性時,你可能需要調用View的invalidate()方法通知屏幕使用更新的動畫值來重繪。這種代碼應該在onAnimationUpdate()的回調函數中調用。比如改變color屬性後,只有調用屏幕重繪方法纔會實現動畫效果。所有的View類中已存在的setter方法,如setalpha()和settranslationx()會在方法內部刷新View,所以當你試圖改變這些屬性時,你並不需要重新調用invalidate()方法

如何使用AnimatorSet管理多個動畫

在許多情況下,你想在另一個動畫開始或者結束時執行一個動畫,Android系統支持將多個動畫同時放入一個AnimatorSet中,使得你可以指定這些動畫是同時執行、按順序執行或者一定延遲後執行。也可以在AnimatorSet中放入AnimatorSet。

下面的代碼示例來自於 Bouncing Balls 示例中(已被改的簡單了一些),AnimatorSet中包涵了以下的動畫:

  1. 執行bounceAnim
  2. 同時執行squashAnim1, squashAnim2, stretchAnim1, and stretchAnim2
  3. 執行bounceBackAnim
  4. 執行fadeAnim
AnimatorSet bouncer = new AnimatorSet();
bouncer.play(bounceAnim).before(squashAnim1);
bouncer.play(squashAnim1).with(squashAnim2);
bouncer.play(squashAnim1).with(stretchAnim1);
bouncer.play(squashAnim1).with(stretchAnim2);
bouncer.play(bounceBackAnim).after(stretchAnim2);
ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f);
fadeAnim.setDuration(250);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(bouncer).before(fadeAnim);
animatorSet.start();

如何實現動畫事件監聽

在動畫執行的過程中,你可以監聽一個動畫的持續時間與下面的事件

  • Animator.AnimatorListener

    • onAnimationStart() - 當動畫開始執行時被調用
    • onAnimationEnd() - 當動畫結束時被調用
    • onAnimationRepeat() - 當動畫重複時被調用
    • onAnimationCancel() - 當動畫被取消時被調用,無論動畫如何結束的,同時也會調用onAnimationEnd()方法
  • ValueAnimator.AnimatorUpdateListener

    • onAnimationUpdate() - 動畫的每一幀都會被調用. 監聽這個接口,並使用計算得到的數值(即getAnimatedValue()方法)來修改你希望在當前動畫中發生改變的對象的屬性。

    • 同ObjectAnimator一樣,當你改變某些對象的某些屬性時,你可能需要調用View的invalidate()方法通知屏幕使用更新的動畫值來重繪。這種代碼應該在onAnimationUpdate()的回調函數中調用。改變color屬性後,只有調用屏幕重繪方法纔會實現動畫效果。所有的View類中已存在的setter方法,如setalpha()和settranslationx()會在方法內部刷新View,所以當你試圖改變這些屬性時,你並不需要重新調用invalidate()方法

如果你不想實現所有的animator.animatorlistener接口的方法。那麼你可以選擇重寫AnimatorListenerAdapter類提供的空的實現方法。

下面是一個 Bouncing Balls 項目的示例,爲了調用onAnimationEnd() 回調,創建了一個新的AnimatorListenerAdapter,代碼如下

ValueAnimatorAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f);
fadeAnim.setDuration(250);
fadeAnim.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator animation) {
    balls.remove(((ObjectAnimator)animation).getTarget());
}

如何實現ViewGroups的動畫變化

屬性動畫對ViewGroup的內部成員改變的動畫支持跟對View的動畫支持一樣出色

當一個ViewGroup內部的layout發生改變時,你可以使用LayoutTransition類對其添加動畫支持。當你對ViewGroup內部的View調用setVisibility()方法時,View本身可以產生對應的消失或者顯示的動畫效果。當你添加或者移除View時,也有有對應的位移動畫產生。你可以通過調用LayoutTransition的setanimator()方法對某個對象指定下面的某個動畫常量:

  • APPEARING - 在容器中的成員出現時的動畫。
  • CHANGE_APPEARING - 出現在容器的由於一個成員添加而引起的變化時的動畫。
  • DISAPPEARING - 在容器中的成員消失時的動畫.
  • CHANGE_DISAPPEARING - 出現在容器的由於一個成員消失而引起的變化時的動畫。

你可以定義這四種類型的常量對應的動畫效果,或者直接使用系統默認的效果

下面的LayoutAnimations示例展示瞭如何對一個佈局文件設置一個系統默認的動畫效果,使用起來十分的簡單只需要設置android:animateLayoutchanges屬性爲true即可,示例如下

<LinearLayout
    android:orientation="vertical"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:id="@+id/verticalContainer"
    android:animateLayoutChanges="true" />

設置這個屬性爲true,當有Views添加或被移除時,其內部的所有控件都會有動畫效果的展示。

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