概覽
安卓為UI元素和自己繪製2D、3D圖形提供了一系列的API,這篇文章介紹了這些API的主要用法。
動畫
安卓框架提供了兩種動畫系統:屬性動畫(property animation)和檢視動畫(view animation)。兩種動畫效果都可以使用,但是通常情況下推薦使用屬性動畫(property animation),因為它更靈活並且有更多特性。除了這兩種外,你還可以使用幀動畫(Drawable animation),這種動畫使用圖片資源逐幀展示。
屬性動畫(property animation):
在安卓3.0(API11)引進,屬性動畫允許你對任何物件的屬性進行動畫處理,包括未在螢幕上展示的物件。屬性動畫可以擴充套件,並且允許你自定義屬性。
檢視動畫(View Animation)
檢視動畫只能用於views。相對來說它能提供幾乎滿足你需求的所有動畫。
幀動畫(Drawable Animation)
幀動畫可以逐幀顯示圖片,就像電影一樣。這種動畫在你想要顯示類似於進度一類的動畫時是有用的。
2D和3D圖形
在編寫應用程式時,重要的是要考慮你的圖形需求是什麼。不同的圖形任務最好用不同的技術來完成。 例如,用於靜態應用的圖形和動畫應當與用於互動式遊戲的圖形和動畫不同地實現。 在這裡,我們將討論在Android上繪製圖形的幾個選項,以及它們最適合的任務。
畫布和圖片(Canvas and Drawables)
Android提供了一組View小部件,為各種使用者介面提供了一些通用功能。 你還可以擴充套件這些小部件以修改它們的外觀或行為方式。 此外,莫可以使用Canvas類中包含的各種繪製方法來繪製自己的自定義2D渲染,或者為按鈕或逐幀動畫之類的內容建立Drawable物件。
硬體加速
從安卓3.0引入,允許你是用硬體特性來更好的繪製你的畫布。
openGL
Android通過Android框架API以及本地開發工具包(NDK)可以支援支援OpenGL ES 1.0和2.0。當你想要為您的應用程式新增Canvas API不支援的一些圖形增強功能時,或者您希望獨立於平臺並且不要求高效能時,可以使用安卓框架API。與NDK相比,使用框架API有一個效能損失,因此對於許多圖形密集型應用程式,如遊戲,使用NDK更好(重要的是,你仍然可以使用框架API獲得足夠的效能。例如,Google Body應用程式完全使用框架API開發)。如果你有很多原生程式碼,你想移植到Android,使用NDK的OpenGL也是有用的。
屬性動畫(Property Animation)
屬性動畫是一個強大的框架,幾乎允許你為任何東西做動畫。你可以定義隨時間更改而改變物件屬性的動畫,而不用關心它是不是在螢幕上。屬性動畫在指定的時間內更改屬性值。要設定動畫,需要指定物件屬性,例如物件在螢幕上的位置,設定時間,設定中間值。
屬性動畫中你可以指定下列特性:
- Duration(過度時間) 定義動畫的過渡時間,末日呢是300ms
- Time interpolation 你可以指定計算屬性的值作為動畫當前已用時間的函式。
- Repeat count and behavior 你可以指定是否在到達持續時間結束時重複動畫,以及重複動畫的次數。你還可以指定是否要反轉播放動畫。 將其設定為反向播放動畫,然後反覆向後播放,直到達到重複次數。
- Animator sets 你可以將多個動畫合為一組,包括同時播放、順序播放或在指定延遲後播放的方式。
- Frame refresh delay 你可以指定重新整理頻率,預設情況下是每10ms重新整理一次,但是程式重新整理頻率取決於系統的整體忙碌程度。
屬性動畫是如何工作的
首先讓我們來看一個簡單的例子:
圖1描述了使用其X軸屬性的動畫物件,表示在螢幕上水平位置的移動。動畫的持續時間40ms,行進距離40畫素,這樣每10ms水平移動10畫素。圖示的是線性插值動畫,速度保持恆定。
你也可以指定非線性插值方式。圖2表示的是在動畫開始時加速,動畫結束時減速的動畫過程。仍然是40ms移動40個畫素,但是移動過程是非線性的。
圖3描述了動畫的主要的類的彼此之間的工作
ValueAnimator跟蹤當前動畫的時間,例如動畫執行了多少時間,以及單籤的屬性值。
ValueAnimator封裝了一個定義動畫插值器的TimeInterpolator和定義TypeEvaluator。例如在圖2中,使用的TimeInterpolator是AccelerateDecelerateInterpolator,使用的TypeEvalutor是IntEvaluator。
要啟動動畫,請建立ValueAnimator,併為其設定動畫屬性的起始值和結束值,以及動畫的持續時間。 當你呼叫start()時,動畫開始。在整個動畫期間,ValueAnimator根據動畫的持續時間和已經過去的時間,計算0和1之間的已過比例。 已過比例表示動畫已完成的時間百分比,0表示0%,1表示100%。 例如,在圖1中,在t = 10ms時的經過比例將是0.25,因為總持續時間是t = 40ms。
當ValueAnimator計算完已經完成的函式後,它呼叫當前設定的TimeInterpolator來計算接下來的插值函式。 插值函式將經過的函式對映到考慮了設定的時間新插值函式。 例如,在圖2中,因為動畫緩慢加速,所以插值函式(大約.15)小於經過的函式(.25),在t = 10ms。 在圖1中,插值總是與經過的相同。
當計算插值函式時,ValueAnimator呼叫相應的TypeEvaluator,根據動畫的插值函式,起始值和結束值計算你正在進行動畫的屬性的值。 例如,在圖2中,插值函式在t = 10ms時為.15,因此此時的x軸屬性值為.15 X(40 - 0)或6。
屬性動畫如何區別於檢視動畫
檢視動畫提供只對view物件進行處理的功能,因此如果你對非view進行動畫處理,必須實現自己的程式碼。檢視動畫系統也受到約束,因為它僅將View物件的幾個屬性暴露給動畫,例如檢視的縮放和旋轉,而沒有背景顏色。
補間動畫可以對View物件的內容執行一系列簡單的變換(位置,大小,旋轉和透明度)。所以,如果你有一個TextView物件,你可以移動,旋轉,增長或收縮文字。 如果它有一個背景影象,背景影象將隨文字一起變換。 動畫包提供了補間動畫中使用的所有類。
檢視動畫系統的另一個缺點是,它只是在繪製檢視時修改,而不是實際的View本身。例如,如果你使一個按鈕在螢幕上移動,按鈕移動繪製正確,但是你可以點選按鈕的實際位置不會改變,所以你必須實現自己的邏輯來處理這個。
使用屬性動畫,上邊提到的檢視動畫的缺點全都沒有,你可以操作檢視和非檢視物件。屬性動畫在執行動畫方式上也很好,你可以為要製作動畫的屬性(如顏色,位置或者大小)分配動畫製作器,並可以定義動畫的各個方面,例如多個動畫製作工具的插值和同步。
然而,使用檢視動畫會比屬性動畫有較少的設定和程式碼編寫。如果檢視動畫能滿足你現在有的程式,就不需要使用屬性動畫,也可以結合兩者使用。
API概覽
Animators
在檢視動畫中已經定義了很多動畫插值器,你也可以在屬性動畫中使用他們。Animator類為建立動畫提供了一個基礎框架,正常情況下你不不鞥使用這個類,它只提供了很少的功能,必須要通過繼承來擴充套件它,下面是它的子類:
類 | 描述 |
---|---|
ValueAnimator | 屬性動畫的主要計時引擎,計算要需要使用動畫的屬性的值。它具有計算動畫值幷包含每個動畫的時間細節的所有的核心功能,關於動畫是否重複執行的資訊,接收更新時間的監聽器以及設定自定義型別的能力。動畫屬性有兩個部分:計算動畫值,設定動畫值。ValueAnimator不執行第二部分,因此你必須自己監聽有ValueAnimator計算的值的更新,並修改邏輯物件。 |
ObjectAnimator | ValueAnimator的子類,允許您將目標物件和物件屬性設定為動畫。 此類在為動畫計算新值時相應地更新屬性。 通常情況下使用ObjectAnimator,因為它使得對目標物件的動畫過程更容易。 但是,你有時需要直接使用ValueAnimator,因為ObjectAnimator還有其他一些限制,例如需要在目標物件上存在特定的方法。 |
AnimatorSet | 將一組動畫有機的結合起來。你可以設定為同時播放,順序播放,或者在指定延時後執行動畫 |
Evaluators
Evaluators 告訴了屬性動畫如何根據給定的屬性計算值。獲取由Animator類提供的時間資料,動畫的開始和結束值,並基於這些資料計算屬性的值。以下是一些Evaluators:
類/介面 | 描述 |
---|---|
IntEvaluator | 預設的計算int型屬性的Evaluator |
FloatEvaluator | 預設的計算float型屬性的Evaluator |
ArgbEvaluator | 預設的計算顏色屬性(16進位制)的Evaluator |
TypeEvaluator | 一個允許你建立自己的Evaluator的介面。如果要對不是int,float或color的物件屬性進行動畫處理,則必須實現TypeEvaluator介面以指定如何計算物件屬性的動畫值。如果要處理那些型別與預設行為不同,也可以為int,float和color值指定自定義TypeEvaluator。 |
時間插值器定義動畫中的具體值如何對應時間的函式計算。例如,您可以指定動畫在整個動畫中線性發生,這意味著動畫在整個時間內均勻移動,或者您可以指定動畫以使用非線性時間,例如,在開始時加速,在結束時減速的動畫。表3描述了android.view.animation中包含的內插器。 如果所提供的插值器都不適合您的需要,請實現TimeInterpolator介面並建立自己的外掛。
Interpolators
類/介面 | 描述 |
---|---|
AccelerateDecelerateInterpolator | 開始和結束時慢,中間加速的插值器 |
AccelerateInterpolator | 先緩慢後快速的加速器 |
AnticipateInterpolator | 開始正向前然後反向的插值器 |
AnticipateOvershootInterpolator | 先反向在正向超過目標值最後達到目標值 |
BounceInterpolator | 在結束時反彈的插值器 |
CycleInterpolator | 動畫重複指定次數的週期插值器 |
DecelerateInterpolator | 快速開始然後減速的插值器 |
LinearInterpolator | 速度恆定的線性插值器 |
OvershootInterpolator | 正向超過目標值然後返回目標值 |
TimeInterpolator | 介面,實現你自己的插值器 |
使用ValueAnimator
ValueAnimator類允許你通過指定一組int,float或顏色設定動畫的持續時間,從而為某種型別的值設定動畫。 您可以通過呼叫其工廠方法之一獲得一個ValueAnimator:ofInt(),ofFloat()或ofObject()。 例如:
ValueAnimator animation = ValueAnimator.ofFloat(0f, 1f);
animation.setDuration(1000);
animation.start();複製程式碼
在此程式碼中,當start()方法執行時,ValueAnimator開始計算動畫的值(在0和1之間),持續時間為1000 ms。
您還可以通過執行以下操作,指定自定義動畫:
ValueAnimator animation = ValueAnimator.ofObject(new MyTypeEvaluator(), startPropertyValue, endPropertyValue);
animation.setDuration(1000);
animation.start();複製程式碼
在此程式碼中,當start()方法執行時,ValueAnimator開始計算startPropertyValue和endPropertyValue之間的動畫值,使用由MyTypeEvaluator提供的邏輯,持續時間為1000 ms。
然而,第一段程式碼片段對物件沒有實際影響,因為ValueAnimator不直接對物件或屬性操作。 你想做的最可能的事情是修改要用這些計算值的物件。 你可以通過在ValueAnimator中定義監聽器以在動畫的生命週期內適當地處理重要事件(例如幀更新)來實現此目的。 當實現偵聽器時,您可以通過呼叫getAnimatedValue()獲取特定幀重新整理的計算值。
使用ObjectAnimator
ObjectAnimator是ValueAnimator的子類,並結合了定時引擎和ValueAnimator的值計算,以及為目標物件的命名屬性設定動畫的能力。 這使得對任何物件使用動畫更容易,因為你不再需要實現ValueAnimator.AnimatorUpdateListener,物件的屬性自動更新。
例項化一個ObjectAnimator類似於一個ValueAnimator,但你也指定物件和該物件的屬性(作為一個String)的名稱以及值之間的動畫:
ObjectAnimator anim = ObjectAnimator.ofFloat(foo, "alpha", 0f, 1f);
anim.setDuration(1000);
anim.start();複製程式碼
要使ObjectAnimator正確的更新屬性,必須執行以下操作:
物件的屬性必須有set
- 可以的情況下將setter方法新增到類中
- 如果你可以更改屬性的包裝類,可以使包裝類接受有效的setter方法,並將其轉發到原始物件
- 使用ValueAnimator類
如果你在ObjectAnimator工廠方法中的value的引數僅指定一個值,那麼將會假定他是動畫的結束值。因此你的物件屬性必須要有一個getter方法,用於獲取動畫的起始值。gettter方法必須是get
ObjectAnimator.ofFloat(targetObject,“propName”,1f)複製程式碼
根據你要動畫化的屬性或物件,你可能需要在檢視上呼叫invalidate()方法,以強制螢幕使用更新的動畫值重繪本身。你可以在onAnimationUpdate()回撥中做到這一點。例如,對一個Drawable物件的顏色屬性進行動畫處理只會在該物件重繪本身時更新螢幕。 View上的所有設定的屬性,例如setAlpha()和setTranslationX(),所以當使用新值呼叫這些方法時,您不需要使invalidate。
下面看幾種效果:
1.AccelerateDecelerateInterpolator
效果:動畫開始的時候慢速,慢慢加速,後邊減速
2.AccelerateInterpolator
效果:動畫慢慢加速,最後達到速度最快
3.AnticipateInterpolator
效果:先反向運動一段,然後正向運動
4.AnticipateOvershootInterpolator
效果:先反向運動一小段距離,然後超過終點一段距離,最後回到終點。
5.BounceInterpolator
效果:彈跳效果
6.CycleInterpolator
效果:迴圈完成多次,在構造器中傳入引數,這個引數就是迴圈的次數,中是例子2次
7.DecelerateInterpolator
效果:速度越來越慢
8.LinearInterpolator
效果:線性勻速運動
9.OvershootInterpolator
效果:超過終點然後返回
使用AnimatorSet編排多個動畫
在多數情況下,你想在一個動畫開始或者結束的時候啟動另一個動畫,Android系統允許你將動畫捆綁在一起成為AnimatorSet,以便可以指定是同時、按順序啟動動畫還是在指定的延遲後啟動動畫。 您還可以將AnimatorSet物件巢狀在彼此之內。
下面的例子是從Bouncing Balls中提取的一段程式碼,播放順序如下:
- 播放bounceAnim。
- 同時播放squashAnim1, squashAnim2, stretchAnim1, 和stretchAnim2。
- 播放bounceBackAnim.
- 播放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();複製程式碼
下面看兩個例子
1.按順序播放動畫
2.按順序播放動畫的同時播放透明度變化
Note:此處注意,在一個set中不能複用同一個動畫
動畫監聽器
你可以在動畫執行期間監聽一些重要的事件。
Animator.AnimatorListener
- onAnimationStart() 動畫啟動時呼叫
- onAnimationEnd() 動畫結束時呼叫
- onAnimationRepeat() 動畫重複時呼叫
onAnimationCancel() 在動畫被取消時呼叫,同時會呼叫onAnimationEnd(), 無論它是怎樣被結束的。
ValueAnimator.AnimatorUpdateListener
- onAnimationUpdate() 每一幀變化都會呼叫。使用者監聽此事件以使用動畫期間ValueAnimator生成的計算值。 要使用該值,請查詢傳遞到事件的ValueAnimator物件,以使用getAnimatedValue()方法獲取當前的動畫值。 如果使用ValueAnimator,則需要實現此偵聽器。
根據你要動畫化的屬性或物件,你可能需要在控制元件上呼叫invalidate(),以強制螢幕的該區域使用新的動畫值重繪本身。 例如,對一個Drawable物件的顏色屬性進行動畫處理只會在該物件重繪本身時更新螢幕。 View上的所有屬性設定,例如setAlpha()和setTranslationX()使Viewinvalidate,所以當使用新值呼叫這些方法時,您不需要使呼叫invalidate。
如果不想實現Animator.AnimatorListener介面的所有方法,你可以擴充套件AnimatorListenerAdapter類,AnimatorListenerAdapter類提供了可以選擇覆蓋的方法的空實現。
例如,Bouncing Balls例子中建立了一個只有onAnimationEnd回掉方法的AnimatorListenerAdapter。
ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f);
fadeAnim.setDuration(250);
fadeAnim.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator animation) {
balls.remove(((ObjectAnimator)animation).getTarget());
}複製程式碼
動畫對ViewGroup的佈局更改
屬性動畫系統能夠為ViewGroup物件提供像對View物件一樣簡單的方法來製作動畫。
你可以使用LayoutTransition類在一個ViewGroup種使用動畫來更改佈局。當你為新增和刪除的動作新增動畫時,使用android.view.View.GONE,VISIBLE,INVISIBLE等或者呼叫set Visibility()方法設定可見不可見的時候,你可以呼叫setAnimator()並傳入具有以下LayoutTransition常量的Animator物件,在LayoutTransiton種定義動畫:
- APPEARING - 一個在容器中新增item時候的動畫的標記
- CHANGE_APPEARING - 一個在容器中由於新增新的item而引起其他條目變化的動畫標記
- DISAPPEARING -一個在容器中消失的動畫的標
- CHANGE_DISAPPEARING - 一個由於某個item消失而引起的其他item變化的動畫
API演示中的LayoutAnimations示例顯示瞭如何定義佈局轉換的動畫,然後在要設定動畫的View物件上設定動畫。
LayoutAnimationsByDefault及其相應的layout_animations_by_default.xml佈局資原始檔顯示如何在XML中為ViewGroups啟用預設佈局轉換。 你唯一需要做的是為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中新增或刪除的檢視以及ViewGroup中的其餘檢視建立動畫。
使用TypeEvaluator
如果要為Android系統未知的型別設定動畫,可以通過實現TypeEvaluator介面建立自己的evaluator 。 Android系統已知的型別是int,float或color,它們由IntEvaluator,FloatEvaluator和ArgbEvaluator型別evaluator 支援。
在TypeEvaluator介面中只有一種方法,即evaluate()方法。這允許你使用的animator在動畫的當前點為動畫屬性返回適當的值。 FloatEvaluator類演示如何做到這一點:
public class FloatEvaluator implements TypeEvaluator {
public Object evaluate(float fraction, Object startValue, Object endValue) {
float startFloat = ((Number) startValue).floatValue();
return startFloat + fraction * (((Number) endValue).floatValue() - startFloat);
}
}複製程式碼
Note:當ValueAnimator(或ObjectAnimator)執行時,它計算動畫的當前已過比例(0到1之間的值),然後根據你使用的插值器器計算插值號。 插值函式是你的TypeEvaluator通過fraction引數接收的,所以你不必在計算動畫值時考慮插值器。
使用Interpolators
插值器定義動畫中的具體值與時間的函式關係。例如你可以指定動畫在整個動畫期間內線性運動,你也可以使用非線性運動,加速和減速運動。
動畫系統中的插值器從動畫製作器接收表示動畫的經過時間的函式。 插值器修依靠函式以與其目標提供的動畫型別一致。 Android系統在android.view.animation包中提供了一組常見的內插器。 如果這些都不符合你的需要,你可以實現TimeInterpolator介面並建立自己的插值器。
作為示例,下面比較預設內插器中的AccelerateDecelerateInterpolator和LinearInterpolator如何計算插值函式。 LinearInterpolator對已過的沒有影響。 AccelerateDecelerateInterpolator加速然後減速。
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;
}複製程式碼
下面的表中列出了插值器在持續1000ms的過程種對應的數值:
時間 | Linear函式值 | Accelerate/Decelerate函式值 | |
---|---|---|---|
0 | 0 | 0 | |
200 | .2 | .1 | |
400 | .4 | .345 | |
600 | .6 | .8 | |
800 | .8 | .9 | |
1000 | 1 | 1 |
上表中可以看到,Linear是勻速運動,每200ms移動0.2。AccelerateDecelerateInterpolator是變速運動,200-600ms時加速很快,600-1000ms時變化慢。
定義關鍵幀
關鍵幀物件由時間/值的鍵值對組成,允許您在動畫的特定時間定義特定狀態。每個關鍵幀也可以有自己的插值器,以控制動畫在前一個關鍵幀的時間和該關鍵幀的時間之間的間隔中的行為。
要例項化一個Keyframe物件,必須使用ofInt(),ofFloat()或ofObject()的工廠方法之一來獲取相應型別的關鍵幀。然後呼叫ofKeyframe()工廠方法來獲取PropertyValuesHolder物件。 一旦你有了物件,你可以通過傳入PropertyValuesHolder物件和物件來獲得animator。 以下程式碼段演示瞭如何執行此操作:
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);複製程式碼
控制元件動畫
屬性動畫系統允許對View物件使用流線型動畫,並且提供了超過檢視動畫系統的一些優點。 檢視動畫系統通過更改繪製物件的方式來轉換檢視物件。 這是在每個View的容器中處理的,因為View本身沒有可操作的屬性。 這導致View被動畫化,但是View物件本身沒有改變。 這導致物件,即使它被繪製在螢幕上的不同位置,仍然存在於其原始位置。在Android 3.0中,新增了新的屬性和相應的getter和setter方法以消除此缺點。
屬性動畫系統可以通過更改View物件中的實際屬性來在螢幕上更新View。 此外,View還會在其屬性更改時自動呼叫invalidate()方法來重新整理螢幕。 的View類中的新屬性是:
- translationX & translationY: 這些屬性控制檢視作為從其佈局容器設定的左側和頂部座標的增量的位置。
- rotation & rotationX & rotationY: 這些屬性控制2D(旋轉屬性)中的旋轉和圍繞中心點3D的旋轉。
- scaleX and scaleY: 2D上控制縮放
- pivotX and pivotY: 控制中心點的位置,圍繞該點旋轉和縮放變換。 預設情況下,該點位於物件的中心。
- x and y: 用於在其容器中描述檢視的最終位置,作為左側值和頂部值以及translationX和translationY值的總和。
- alpha: 描述View的透明度,0表示全透明,1表示不透明。
為了使View物件的屬性擁有動畫,例如他的顏色或者旋轉角度,你要做的就是建立一個property animator物件並且指定你想要動畫的屬性。
ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f);複製程式碼
ViewPropertyAnimator動畫
使用ViewPropertyAnimator進行動畫處理。ViewPropertyAnimator提供了一種簡單的方法來使用單個底層Animator物件來並行地對檢視的多個屬性進行動畫。 它的行為非常像一個ObjectAnimator,因為它修改View的屬性的實際值,但是當同時對許多屬性更有效。 此外,使用ViewPropertyAnimator的程式碼更簡潔,更容易閱讀。 以下程式碼片段顯示了在同時對檢視的x和y屬性進行動畫處理時,在使用多個ObjectAnimator物件,單個ObjectAnimator和ViewPropertyAnimator時的差異。
多個動畫
ObjectAnimator animX = ObjectAnimator.ofFloat(myView, "x", 50f);
ObjectAnimator animY = ObjectAnimator.ofFloat(myView, "y", 100f);
AnimatorSet animSetXY = new AnimatorSet();
animSetXY.playTogether(animX, animY);
animSetXY.start();複製程式碼
單個動畫
PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("x", 50f);
PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 100f);
ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvyY).start();複製程式碼
ViewPropertyAnimator
myView.animate().x(50f).y(100f);複製程式碼
在xml檔案種宣告動畫
屬性動畫系統允許您使用XML宣告屬性動畫,而不是以程式設計方式。 通過在XML中定義動畫,您可以輕鬆地在多個活動中重複使用動畫,並更輕鬆地編輯動畫序列。
要將使用新屬性動畫API的動畫檔案與使用舊檢視動畫框架的動畫檔案區分開來,從Android 3.1開始,您應該將屬性動畫的XML檔案儲存在res / animator /目錄中。
以下屬性動畫類具有以下XML標記的XML宣告支援:
- ValueAnimator -
- ObjectAnimator -
- AnimatorSet -
下面的例子是順序播放兩個動畫,第一個動畫集合中的兩個動畫是同時播放的:
<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();複製程式碼
最後附上github地址:
Demo