Android動畫效果屬性--Property Animation使用2

用ValueAnimator來製做動畫 html

ValueAnimator 類經過設定動畫過程當中的int、float或顏色值,來指定動畫播放期間的某些類型的動畫值。經過ValueAnimator類的一個工廠方法來獲取一個 ValueAnimator對象:ofInt()、ofFloat()、ofObject()。例如: android

1
2
3

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

animation.setDuration(1000);

animation.start();


在這段代碼中,當start()方法開始執行時,ValueAnimator對象會在1000毫秒的動畫期間內,在0和1之間開始計算動畫的值。 編程

還能夠經過下面的作法來指定自定義的動畫類型: 框架

1
2
3

ValueAnimator animation = ValueAnimator.ofObject(newMyTypeEvaluator(), startPropertyValue, endPropertyValue);

animation.setDuration(1000);

animation.start();


在 這段代碼中,在start()方法開始執行的時候,ValueAnimator對象會在1000毫秒的動畫期間內,使用由MyTypeEvaluator 對象提供的邏輯,在startPropertyValue和endPropertyValue之間,開始計算動畫的值。 編輯器

可是,在前一個代碼片斷中,不會對一個對象造成實際的影響,由於ValueAnimator對 象沒有直接在對象或屬性上執行操做。這麼作的最大多是用這些計算值來修改那些想要動畫效果的對象。經過定義ValueAnimator類中響應的事件監 聽器,來處理動畫執行期間的重要事件,如幀更新等。當監聽器執行的時候,就可以經過調用getAnimateValue()方法得到指定幀的刷新的計算 值。有關監聽器的更多信息,請看「動畫監聽器」。 函數

用ObjectAnimator來製做動畫 佈局

ObjectAnimator類 是ValueAnimator類的一個子類,而且把時序引擎和ValueAnimator對象的計算值組合到一塊兒,讓目標對象的命名屬性具有動畫能力。這 樣使得讓任意對象具備動畫效果變的更加容易,如不在須要實現ValueAnimator.AnimatorUpdateListener接口,由於被動畫 的屬性會自動的更新。 動畫

實例化一個ObjectAnimator對象與實例化一個ValueAnimator對象相似,可是,它還須要跟動畫期間的參數一塊兒,指定動畫對象和對象動畫屬性(用一個字符串)的名字: lua

1
2
3

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

anim.setDuration(1000);

anim.start();


要正確的更新ObjectAnimator對象的屬性,必須作如下事情: spa

1. 動 畫效果的屬性必須有一個set<propertyName>格式的設置器方法。由於在動畫處理期間,ObjectAnimator對象會自動 的更新對應的動畫效果屬性,因此它必須使用這個設置器方法來訪問對應的屬性。例如,若是屬性名是foo,那麼就須要有一個setFoo()方法,若是這個 設置器方法不存在,你有三種選擇:

   A. 若是你權利這麼作,就要在這個類中添加設置器方法;

   B. 使用一個你有權改變的包裝器類,而且這個包裝器可以用一個有效的設置方法來接收動畫值,並且還要可以把這個值轉發給初始對象。

   C. 使用ValueAnimator類來代替。

2.  如 果你只在ObjectAnimator類的一個工廠方法中指定了一個values…參數,那麼該值會被假定爲動畫的結束值。所以,該對象的動畫效果屬性就 必需要有一個獲取方法,用於得到動畫的開始值。這個獲取方法必須使用get<propertyName>()格式。例如,屬性是foo,就必 須有一個getFoo方法。

3.  動畫屬性的獲取(若是須要)和設置方法必須操做相同類型的指定給ObjectAnimator對象開始 和結束值。例如,若是構建一個下面這樣的ObjectAnimator對象,就必需要有targetObejct.setPropName(float) 和targetObject.getPropName(float)方法:


1

ObjectAnimator.ofFloat(targetObject,"propName", 1f)



4.  根 據屬性或對象上的動畫效果,可能須要調用View對象上的invalidate()方法,在更新動畫效果時,強制屏幕重繪本身。在 onAnimationUpdate()回調方法中作這件事情。例如,一個繪圖對象的顏色屬性的動畫效果,在隊形重繪本身時,纔會將變化結果更新到屏幕 上。在View對象上的全部的屬性的設置器,如setAlpha()和setTranslationX()會正確的讓View對象失效,所以在調用這些方 法設置新的值時候,你不需作失效這件事。有關監聽器的更多信息,請看「動畫監聽器」。

用AnimatorSet類來編排多個動畫

在不少場景中,一個動畫的播放要依賴與另外一個動畫的開始或結束。Android系統讓你把這些相互依賴的動畫綁定到一個AnimatorSet對象中,以便可以指定它們是同時的、順序的、或在指定的延時以後來播放。AnimatorSet對象也可以彼此嵌套。

如下示例代碼來自Bouncing Balls示例,它按照如下方式播放Animator對象:

1.  播放bounceAnim

2.  同時播放squashAnim一、squashAnim二、stretchAnim1和stetchAnim2

3.  播放bounceBackAnim

4.  播放fadeAnim

1
2
3
4
5
6
7
8
9
10
11

AnimatorSet bouncer =newAnimatorSet();

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 =newAnimatorSet();

animatorSet.play(bouncer).before(fadeAnim);

animatorSet.start();

關於如何使用動畫集的完整示例,請看APIDemo中的Bouncing Balls示例。

動畫監聽器

使用下列介紹的監聽器可以監聽動畫播放期間的重要事件:

1.  Animator.AnimatorListener

onAnimationStart()---動畫開始的時候被調用

onAnimationEnd()---動畫結束的時候被調用,它無論動畫是如何結束的。

onAnimationRepeate()---動畫重複播放的時候被調用

onAnimationCancel()---動畫被取消播放的時候被調用。

2.  ValueAnimator.AnimatorUpdateListener

onAnimationUpdate()--- 在動畫的幀上調用這個方法。經過監聽這個事件,使用在動畫期間由ValueAnimator對象產生的計算值。要使用這個值,就要用 getAnimateValue()方法查詢傳遞到事件中的ValueAnimator對象,以便得到當前的動畫值。若是使用ValueAnimator 類,那麼實現這個監聽器是必須的。

根據屬性或對象的動畫效果,可能須要調用View對象上的invalidate()方法,用新的動畫值來 強制屏幕的指定區域進行重繪。例如,Drawable對象的顏色屬性的動畫效果,在對象重繪本身的時候,只會致使屏幕的更新。在View對象上的全部屬性 的設置器,如setAlpha()、setTranslationX()等方法都會正確的讓View對象失效,所以在調用這些方法設置新值的時候,你不需 要讓該View對象失效。

若是不實現Animator.AnimatorListener接口的全部方法,你可以繼承 AnimatorListenerAdapter類,來代替對Animator.AnimatorListener接口的實現。 AnimatorListenerAdapter類對這些方法提供了空的實現,你能夠選擇性的重寫這些方法。

例如,APIDemo中的Bouncing Balls示例就只建立了一個AnimatorListenerdapter類的onAnimationEnd()回調方法:

1
2
3
4
5
6

ValueAnimatorAnimator fadeAnim = ObjectAnimator.ofFloat(newBall,"alpha", 1f, 0f);

fadeAnim.setDuration(250);

fadeAnim.addListener(newAnimatorListenerAdapter() {

public void onAnimationEnd(Animator animation) {

    balls.remove(((ObjectAnimator)animation).getTarget());

}

對於ViewGroups對象佈局變化的動畫

屬性動畫系統給ViewGroup對象的動畫變化提供了與View對象同樣容易動畫處理方法。

使 用LayoutTransition類在ViewGroup內部處理佈局變化的動畫。當調用一個View對象的setVisibility()方法,或者 設置該View的GONE常量,或者把該View對象添加到ViewGroup中(或者從ViewGroup中刪除)時,在ViewGroup內部的 View對象就可以實現時隱時現的動畫效果。當在ViewGroup對象中添加或刪除View對象時,其中的其餘View對象也可以動畫移動到新的位置。 在LayoutTransition對象內經過調用setAnimator()方法,而且在傳遞給該方法的Animator對象參數中帶有下列 LayoutTransition常量之一,就可以定義該常量所表明的動畫:

1.  APPEARING---一個標記,它指示要在容器中正在顯示的項目上運行動畫;

2.  CHANGE APPEARING---一個標記,它指示在容器中因爲新項目的出現而致使其餘項目變化所要運行的動畫;

3.  DISAPPEARING---一個標記,它指示一個從容器中消失的項目所要運行的動畫;

4.  CHANGE_DISAPPEARING---一個標記,它指示因爲一個項目要從容器中消失而致使其餘項目的變化,所要運行的動畫。

可以給這四種事件類型定義自定義動畫,以便定製本身的佈局過渡效果,也能夠告訴動畫系統只使用默認的動畫效果。

在APIDemo中的LayoutAnimations示例,顯示瞭如何給佈局的過渡定義動畫效果,而且在想要動畫效果的View對象上設置動畫。

LayoutAnimationsByDefault 類以及它對應的layout_animations_by_default.xml佈局資源文件顯示瞭如何在XML中啓用ViewGroup對象的默認布 局過渡效果。須要作的事情僅僅是把ViewGroup元素的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,那麼在該ViewGroup對象中添加或刪除View對象,以及ViewGroup對象中其餘的View對象都會自動的具備動畫效果。

使用TypeEvaluator

如 果想要的動畫類型是Android系統所未知的,那麼經過實現TypeEvaluator接口就可以建立本身的評價器。Android系統已知的類型是 int、float或顏色(color),分別有IntEvaluator、FloatEvaluator和ArgbEvaluator類型的評價器所支 持。

在TypeEvaluator接口中只有一個要實現的方法:evaluate()方法。這個方法容許正在使用的動畫處理器返回一個適用於於當前動畫時點動畫屬性值,FloatEvaluator類演示了這個方法是如何作這件事的:

1
2
3
4
5
6
7

public class FloatEvaluator implements TypeEvaluator {

  

    public Object evaluate(float fraction, Object startValue, Object endValue) {

        float startFloat = ((Number) startValue).floatValue();

        returnstartFloat + fraction * (((Number) endValue).floatValue() - startFloat);

    }

}


注意:當ValueAnimator對 象(或ObjectAnimator對象)運行時,它會計算當前的動畫播放比例(一個0到1之間的值),而後根據你所使用的插值類型來計算一個要插入的動 畫的版本。插值比例是由TypeEvaluator對象經過fraction參數接收來的,所以在計算動畫值的時候,不須要考慮插值。

 

使用插補器

插補器定義了怎樣在動畫內指定用於時間函數的計算值。例如,指定貫穿整個動畫期間的線性播放動畫,意味在動畫整個時間裏都是均勻的移動,也可以指定非線性動畫,如:在動畫的開始或結尾部分使用加速或減速的動畫。

在 動畫系統中的插補器會接收一個來自Animator對象的一個比例,它表明了動畫已通過去的時間。插補器修改這個比例,使它與提供的目標動畫類型相吻合。 Android系統在android.view.animation包中提供了一組共通的插補器。若是這個包中沒有適合你須要的,你能夠實現 TimeInterpolator接口來建立本身的插補器。

例如,如下是對 AccelerateDecelerateInterpolator和LinearInterpolator插補器如何計算插補比例的比較。 LinearInterpolator對延時比例沒有影響,AccelerateDecelerateInterpolator會讓動畫加速進入,並減速 退出。如下是這些插補器方法中定義的邏輯:

AccelerateDecelerateInterpolator

1
2
3

public float getInterpolation(float input) {

    return(float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;

}

LinearInterpolator

1
2
3

public float getInterpolation(float input) {

    returninput;

}

下表列出了一個持續1000毫秒的動畫經過插補器所計算的近似值:

播放時間(毫秒)

播放比例/插值比例(線性)

插值比例(加速/減速)

0

0

0

200

0.2

0.1

400

0.4

0.345

600

0.6

0.8

800

0.8

0.9

1000

1

1

如 上表所示,LinearInterpolator插補器的計算結果是勻速變化的,每200毫秒增長0.2。 AccelerateDecelerateInterpolator插補器的計算結果在200毫秒到600毫秒之間比 LinearInterpolator的計算結果要快,而在600毫秒到1000毫秒之間則比LinearInterpolator的計算結果要慢。

關鍵幀

有時間和值構成的Keyframe對象會定義動畫在特定的時間點上特定的狀態。每一個關鍵幀還有它本身的插補器來控制當前關鍵幀與前一個關鍵幀之間的動畫行爲。

要 實例化一個Keyframe對象,必須使用如下工廠方法之一:ofInt()、ofFloat()、或ofObject()。使用這些工廠方法來獲取對應 類型的關鍵幀,而後調用ofKeyframe工廠方法來獲取一個PropertyValuesHolder對象,一旦得到了這個對象,就可以獲得一個在 PropertyValuesHolder對象中傳遞的動畫製做器對象。如下代碼演示瞭如何作這件事情:

Keyframe kf0 = Keyframe.ofFloat(0f, 0f);

Keyframe kf1 = Keyframe.ofFloat(.5f, 360f);

Keyframe kf2 = Keyframe.ofFloat(1f, 0f);

PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2);

ObjectAnimator rotationAnim = ObjectAnimator.ofPropertyValuesHolder(target, pvhRotation)

rotationAnim.setDuration(5000ms);

關於如何使用關鍵幀的完整的示例,狀況APIDemo中的MultiPropertyAnimation示例。

http://developer.android.com/tools/samples/index.html

製做View動畫

屬 性動畫系統容許對View對象的動畫進行簡化處理,而且在視圖動畫系統上提供了一些優勢。視圖動畫系統經過改變View對象的繪製方式來轉換View對 象。這種變換是在在每一個View對象的容器中來處理的,由於View對象自己沒有執行這種處理的屬性。這種處理會致使View對象產生動畫效果,但卻不會 改變View對象自身。這樣即便在屏幕的不一樣的位置上繪製了View對象,該對象依然會保留在它的原始位置上。在Android3.0中,添加了新的屬性 和對象的getter和setter方法,來消除這一缺陷。

屬性動畫系統可以經過改變View對象中的實際屬性,讓View對象在屏幕上展示動畫效果。另外,View對象也會自動的調用invalidate()方法,在屬性發生變化時來屬性屏幕。在View類中便於動畫設置的新屬性有:

1. translationX和translationY:這兩個屬性做爲一種增量來控制着View對象從它佈局容器的左上角座標開始的位置。

2. rotation、rotationX和rotationY:這三個屬性控制View對象圍繞支點進行2D和3D旋轉。

3. scaleX和scaleY:這兩個屬性控制着View對象圍繞它的支點進行2D縮放。

4. pivotX和pivotY:這兩個屬性控制着View對象的支點位置,圍繞這個支點進行旋轉和縮放變換處理。默認狀況下,該支點的位置就是View對象的中心點。

5. x和y:這是兩個簡單實用的屬性,它描述了View對象在它的容器中的最終位置,它是最初的左上角座標和translationX和translationY值的累計和。

6. alpha:它表示View對象的alpha透明度。默認值是1(不透明),0表明徹底透明(不可見)。

要讓一個View對象的屬性具備動畫效果,如它的顏色或旋轉值等,就須要建立一個屬性動畫製做器,並給對象屬性指定想要的動畫效果,如:

ObjectAnimator.ofFloat(myView,"rotation",0f,360f);

用ViewPropertyAnimator製做動畫

ViewPropertyAnimator 類使用一個單一的Animator對象,給一個View對象的幾個動畫屬性平行處理提供一種簡單的方法。它的行爲很是像ObjectAnimator類, 由於它修改了View對象屬性的實際的值,可是當多個動畫屬性同時處理時,它會更加高效。另外,使用ViewPropertyAnimator類的代碼更 加簡潔和易於閱讀。如下代碼片斷顯示了在同時處理View對象的x和y屬性動畫效果時,使用多個ObjectAnimator對象、一個單獨的 ObjectAnimator對象和ViewPropertyAnimator對象之間的差別:

多個ObjectAnimator

1
2
3
4
5

ObjectAnimator animX = ObjectAnimator.ofFloat(myView,"x", 50f);

ObjectAnimator animY = ObjectAnimator.ofFloat(myView,"y", 100f);

AnimatorSet animSetXY =newAnimatorSet();

animSetXY.playTogether(animX, animY);

animSetXY.start();

一個ObjectAnimator對象:

1
2
3

PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("x", 50f);

PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 100f);

ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvyY).start();

ViewPropertyAnimator對象:

1

myView.animate().x(50f).y(100f);

在XML中聲明動畫

屬性動畫系統會讓你用XML來聲明屬性動畫,而不是用編程的方式來作它。經過XML中定義你的動畫,可以更加容易的在多個Activity中重用動畫,而且更加容易的編輯動畫的播放順序。

從 Android3.1開始,要把使用新的屬性動畫的API的動畫文件與那些使用傳統的視圖動畫框架區分開,你應該把屬性動畫的XML文件保存在 res/animator/目錄中(而不是res/anim/)。animator目錄名是可選的,可是若是想要使用Eclipse ADT插件(ADT11.0.0+)中的佈局編輯器,就必須使用animator目錄,由於ADT只搜索res/animator目錄中屬性動畫資源。

如下是屬性動畫類在XML聲明中所使用的對應的XML標籤:

如下示例順序的播放兩組對象動畫,第一組動畫中嵌套了一個同時播放兩個對象的動畫:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

<set android:ordering="sequentially">

    <set>

        <objectAnimator

            android:propertyName="x"

            android:duration="500"

            android:valueTo="400"

            android:valueType="intType"/>

        <objectAnimator

            android:propertyName="y"

            android:duration="500"

            android:valueTo="300"

            android:valueType="intType"/>

    </set>

    <objectAnimator

        android:propertyName="alpha"

        android:duration="500"

        android:valueTo="1f"/>

</set>

爲 了運行這個動畫,在代碼中,必須把這個XML資源填充到一個AnimatorSet對象中,而且在開始播放這個動畫集以前,要把這個動畫集合設置給目標對 象。調用setTarget()方法就能夠方便的把AnimatorSet對象中的全部子對象設置給一個單一的目標對象。如下代碼顯示了作這件事的方法:

1
2
3
4

AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext,

    R.anim.property_animator);

set.setTarget(myObject);

set.start();
相關文章
相關標籤/搜索