屬性動畫簡介
屬性動畫系統是一個強大的框架,可以讓任何對象加上動畫效果。隨著時間的推移,您可以定義一個動畫來改變任何對象屬性,無論它是否顯示在屏幕上。在指定的時間長度,屬性動畫改變屬性值(對象的字段)。通過指定對象屬性來創造動畫效果,比如View在屏幕上的位置,動畫的時長,以及動畫值的改變。
屬性動畫系統可以讓您定義一個動畫的以下特征:
- 持續時間(Duration):你可以指定一個動畫的持續時間。默認長度為300毫秒。
- 時間插值器(Time interpolation):您可以指定屬性的值如何計算作為動畫當前所用時間的函數。
- 重復和行為(Repeat count and behavior):你可以指定是否有一個動畫重復時,達到持續時間的結束,有多少次重復動畫。您還可以指定是否希望動畫反向播放。設置它反向播放動畫,然后反復重復,直到達到重復的數量。
- 動畫設置(AnimatorSets):你可以動畫成邏輯組,同時或順序或在指定的延遲。
- 幀刷新延遲(FrameRefreshDelay):你可以指定如何經常刷新你的動畫幀。默認設置為刷新每10毫秒,但您的應用程序可以刷新幀的速度最終取決于系統的整體是如何的,以及該系統可以為底層定時器服務的速度。 一般使用系統默認即可。
屬性動畫如何工作
首先,讓我們用一個簡單的例子來說明一個動畫。圖1描繪了一個假設的對象,它的X屬性是動畫的,它代表了它在屏幕上的水平位置。動畫的持續時間設置為40毫秒,和旅行的距離為40像素。每10毫秒,這是默認的幀刷新率,對象水平移動10個像素。在為結束,動畫停止,和物體兩端在水平位置40。這是一個用線性插值動畫的例子,這意味著對象以一個恒定的速度移動。
你也可以指定動畫有一個非線性插值。圖2說明了一個假設的對象,在動畫開始時加速,然后減速動畫結束時。該對象仍然在40毫秒內移動40個像素,但非線性。在開始的時候,這個動畫加速到中途點,然后從中途點減速直到動畫結束。如圖2所示,在動畫的開始和結束的距離是小于在中間。
接下來看看屬性動畫系統的重要組成部分是如何計算像上面所示的動畫的動畫系統。圖3描述了主類是如何相互工作的。
ValueAnimator對象保持跟蹤在動畫的整個運行時間,如動畫已經運行多久,當前動畫的值。
ValueAnimator封裝Timeinterpolator和TypeEvaluator,它定義了如何計算對象被動畫對應的值。例如,在圖2中,使用的timeinterpolator對應AccelerateDecelerateInterpolator,TypeEvaluator對應intevaluator。
當開始一個動畫,創建一個ValueAnimator并給它動畫的開始和結束值的屬性,以及動畫的持續時間。當你調用start()方法時 動畫開始。整個動畫中,ValueAnimator計算一個百分比,基于動畫的持續時間和經過了多少時間。經過的數值表示動畫已完成的時間的百分比,0的意思表示 動畫進行了0%和1的意思表示動畫進行100%。例如,在圖1中,在T = 10毫秒的經過的分數將是0.25,因為總的持續時間是t = 40毫秒。
當ValueAnimator完成計算一個動畫時長段,它調用當前設置的TimeInterpolator為計算后的間插值。間插值將所需的值映射到一個新的值作為間插值,即設置。例如,在圖2中,因為動畫慢慢加速,間插值為0.15,小于所經過的值0.25,在T = 10毫秒。在圖1中,差值部分始終是相同的。
API 概述
你可以找到大部分的API android.animation屬性動畫系統。因為視圖動畫系統已經定義了多種插值算法在android.view.animation,你可以在屬性動畫系統使用插值以及。下面的表格描述了屬性動畫系統的主要組件。
Animators提供了用于創建動畫的基本結構。你通常不直接使用這個類,它只提供最低限度的功能,必須擴展到完全支持動畫。下面的子類擴展的動畫類:
Table 1. Animators
-
ValueAnimator
屬性動畫的主要時序引擎,該引擎還計算屬性的值為動畫的值。它擁有所有的核心功能,計算動畫值,并包含每個動畫的時間細節,是否有一個動畫重復的信息,接收更新事件的偵聽器,以及設置自定義類型的能力來評估。有兩片動畫屬性:計算值和設定值的動畫的對象和屬性,正在動畫。ValueAnimator不進行第二片,所以你必須聽由ValueAnimator計算值的更新和修改的對象,你要有你自己的邏輯。 -
ObjectAnimator
ValueAnimator的子類, 允許你設定一個目標對象和對象屬性的動畫。當它為動畫計算一個新值時,該類相應地更新屬性。大部分時間使用ObjectAnimator來做屬性動畫的更新,因為它使用更容易。然而,有時你想直接使用ValueAnimator,因為它更靈活。而ObjectAnimator則有較多一點的限制。 -
AnimatorSet
提供一種機制,使一組動畫一起運行,以便它們相互運行。您可以設置動畫一起播放,順序,或在指定的延遲后。
Evaluators告訴屬性動畫系統如何計算屬性值。他們是由動畫類提供的時序數據,動畫的開始和結束值,并計算動畫數據變化在這個數據基礎上。屬性動畫系統提供以下Evaluators:
Table 2. Evaluators
-
IntEvaluator
屬性動畫默認用來計算Int值 -
FloatEvaluator
屬性動畫默認用來計算Float值 -
ArgbEvaluator
屬性動畫默認用來計算顏色的十六進制值值 -
TypeEvaluator
一個接口,允許你創建自己的計算器。如果你是動畫的對象屬性是不是int,float,或顏色,你必須實現的TypeEvaluator接口指定如何計算對象屬性值的動畫。你也可以指定一個int,自定義的TypeEvaluator浮動,和顏色的值,如果你想處理這些類型不同的默認行為。
插補器(interpolator )定義了一個動畫中的特定值作為時間的函數的計算。例如,您可以指定在整個動畫過程中線性的動畫,使動畫在整個時間內均勻地移動,或者你可以指定要使用的非線性的動畫,加速開始,減速結束動畫時。
Table 3.插補器 Interpolators
其變化率開始和結束緩慢而在中間加速。
其變化率開始緩慢,然后加快。
剛開始向后。然后向前滑動。
剛開始向后,然后超過原來的值,最后返回到最后的值。
值到最后會回彈。
重復指定的次數。
其變化率開始快,然后減速。
變化率不遠,勻速。
值的變化將超過起始值和最后值,然后回來。
一個接口,允許你實現你自己的插補值。
使用ValueAnimator
ValueAnimator類允許你通過指定一組int,float,或色彩值來創建動畫。你調用它的一個工廠方法:ofint(),offloat(),或ofobject()來得到一個ValueAnimator。例如:
ValueAnimator animation = ValueAnimator.ofFloat(0f, 1f);
animation.setDuration(1000);animation.start();
在這段代碼中,start()方法運行時,在時間為1000毫秒期間,ValueAnimator開始在0和1之間計算動畫的值。
您還可以通過以下方式指定一個自定義類型來動畫:
ValueAnimator animation = ValueAnimator.ofObject(new MyTypeEvaluator(), startPropertyValue, endPropertyValue);
animation.setDuration(1000);
animation.start();
使用ObjectAnimator
objectanimator 是ValueAnimator子類,直接利用ValueAnimator值來更新對象的屬性值。這使得動畫物體容易得多,因為你不再需要實施valueanimator.animator updatelistener,因為動畫屬性會根據你的設定的值自動更新。
ObjectAnimator anim = ObjectAnimator.ofFloat(foo, "alpha", 0f, 1f);
anim.setDuration(1000);
anim.start();
想要正確的使用objectanimator更新屬性,你必須做到以下幾點:
objectanimator 更新 動畫的對象屬性必須有一個setter函數的形式設置屬性名。因為objectanimator依賴setter函數來自動更新動畫,它必須能夠與這個setter方法訪問屬性。例如,如果屬性名為foo,你需要有一個setfoo()方法。如果這個setter方法是不存在的,你有三個選擇:
添加setter方法的類如果你有這樣做的權利。
使用包裝類,你必須改變和有包裝獲得有效的setter方法,拿到了它原來的對象權限。
使用ValueAnimator。
在其中的一個objectanimator工廠方法的參數, 如果只指定的一個 value… ,它被認為是動畫的結束值。因此,在你的動畫對象的屬性必須有一個getter函數用于獲取動畫的起始值。getter函數必須在形式上get<propertyName>()。例如,如果屬性名為foo,你需要有一個getfoo()方法。
-
getter(如果需要)和setter方法的動畫的屬性必須使用相同類型的開始和結束值指定ObjectAnimator。例如,你必須targetObject.setPropName(float)和targetObject.getPropName(float) 如果你構建以下ObjectAnimator:
ObjectAnimator.ofFloat(targetObject, "propName", 1f)
取決于屬性或對象動畫,您可能需要調用invalidate()方法在視圖迫使屏幕重繪與更新的動畫本身的值。你這樣做在onAnimationUpdate()回調。
用AnimatorSet編排多個動畫
在很多情況下,你想開始一個動畫,這取決于當另一個動畫開始或結束。Android系統讓你動畫捆綁為一個AnimatorSet,這樣你就可以同時指定是否開始動畫,順序,或在指定的延遲。
Plays bounceAnim.
同時 Plays squashAnim1, squashAnim2, stretchAnim1, and stretchAnim2。
Plays bounceBackAnim
-
Plays 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();
動畫監聽器
onAnimationStart()
在動畫開始被調用onAnimationEnd()
在動畫結束被調用onAnimationRepeat()
當動畫重復自己時候被調用onAnimationCancel()
當動畫被取消的時候調用onAnimationEnd()
無論動畫如何被取消,動畫都會被調用onAnimationUpdate()
每一幀的動畫都會被調用。在一個動畫監聽這個事件獲取ValueAnimator生成的計算值。查詢ValueAnimator對象傳遞到事件與getAnimatedValue獲取當前動畫值()方法來獲取。實現此偵聽器必需是使用ValueAnimator動畫。
對于某些動畫,您可能需要調用invalidate()來重新更新視圖與新動畫本身的值。例如,setAlpha()
,setTranslationX()。
使用動畫
屬性動畫通過在屏幕上通過改變實際的屬性來改變View。此外,View還自動調用invalidate()方法來刷新屏幕在其屬性被更改時。視圖類的新屬性,促進屬性動畫:
ranslationX translationY:這些屬性控制視圖在父布局的左和上的位置。
rotation、rotationX rotationY:這些屬性控制的2D旋轉(rotation)和3D在軸心點的旋轉(rotationX rotationY)。
scaleX 和 scaleY: 這些屬性控制的2d圍繞其軸心點的縮放視圖。
pivotX 和 pivotY: 這些屬性控制樞軸點的位置,旋轉和縮放變換發生。默認情況下,樞軸點位于中心的對象。
x 和 y : 描述視圖在父布局中最終位置,是 left和top的對應 translationX translationY 的總和。
-
alpha: 代表了alpha透明度視圖。這個值是1(不透明的)默認情況下,用一個值0表示完全透明(不可見)。
ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f);
使用插值器
interpolator 定義特定的值如何計算作為時間的函數。例如,您可以指定在整個動畫動畫發生線性,這意味著動畫動作均勻,或您可以指定動畫使用非線性時間,例如,使用加速或減速的開始或者結束動畫。在interpolator 系統接收來自動畫的一小部分代表動畫的運行時間。interpolator 修改這部分動畫的值,并返回動畫。
AccelerateDecelerateInterpolator
public float getInterpolation(float input) { return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;}
LinearInterpolator
public float getInterpolation(float input) { return input;}
從XML使用動畫
屬性動畫系統允許您聲明屬性動畫使用XML而不是做編程。通過定義你的動畫在XML中,可以很容易地重用你的動畫更容易在多個活動和編輯動畫序列。
區分動畫文件使用新的屬性動畫api從那些使用傳統視圖動畫框架,從Android 3.1開始,你應該保存XML文件屬性動畫在res/animator/(而不是res/anim/)。使用 animator 名稱是可選的,但必要的如果你想要使用的布局編輯器工具在Eclipse ADT插件(ADT 11.0.0 +), 因為ADT只搜索res/animator/ 屬性動畫資源。
以下屬性動畫類XML聲明支持以下XML標記:
ValueAnimator<animator>
ObjectAnimator<objectAnimator>
AnimatorSet <set>
下面的例子中兩組對象動畫順序,第一個嵌套組開始兩個對象的動畫:
<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。
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext, R.anim.property_animator);
set.setTarget(myObject);
set.start();