Android Animation各種動畫完全解析
1 背景
不能只分析原始碼呀,分析的同時也要整理歸納基礎知識,剛好有人微博私信讓全面說說Android的動畫,所以今天來一發Android應用的各種Animation大集合。英文厲害的請直接移步參考Android Developer。
Android系統提供了很多豐富的API去實現UI的2D與3D動畫,最主要的劃分可以分為如下幾類:
-
View Animation: 檢視動畫在古老的Android版本系統中就已經提供了,只能被用來設定View的動畫。
-
Drawable Animation: 這種動畫(也叫Frame動畫、幀動畫)其實可以劃分到檢視動畫的類別,專門用來一個一個的顯示Drawable的resources,就像放幻燈片一樣。
-
Property Animation: 屬性動畫只對Android 3.0(API 11)以上版本的Android系統才有效,這種動畫可以設定給任何Object,包括那些還沒有渲染到螢幕上的物件。這種動畫是可擴充套件的,可以讓你自定義任何型別和屬性的動畫。
可以看見,當前應用程式開發涉及的主要動畫也就這三大類,我們接下來以類別為基礎來慢慢展開說明。
2 View Animation(檢視動畫)使用詳解
2-1 檢視動畫概述
檢視動畫,也叫Tween(補間)動畫可以在一個檢視容器內執行一系列簡單變換(位置、大小、旋轉、透明度)。譬如,如果你有一個TextView物件,您可以移動、旋轉、縮放、透明度設定其文字,當然,如果它有一個背景影象,背景影象會隨著文字變化。
補間動畫通過XML或Android程式碼定義,建議使用XML檔案定義,因為它更具可讀性、可重用性。
如下是檢視動畫相關的類繼承關係:
java類名 | xml關鍵字 | 描述資訊 |
---|---|---|
AlphaAnimation | <alpha> 放置在res/anim/目錄下 |
漸變透明度動畫效果 |
RotateAnimation | <rotate> 放置在res/anim/目錄下 |
畫面轉移旋轉動畫效果 |
ScaleAnimation | <scale> 放置在res/anim/目錄下 |
漸變尺寸伸縮動畫效果 |
TranslateAnimation | <translate> 放置在res/anim/目錄下 |
畫面轉換位置移動動畫效果 |
AnimationSet | <set> 放置在res/anim/目錄下 |
一個持有其它動畫元素alpha、scale、translate、rotate或者其它set元素的容器 |
通過上圖和上表可以直觀的看出來補間動畫的關係及種類了吧,接下來我們就詳細一個一個的介紹一下各種補間動畫。
2-2 檢視動畫詳細說明
可以看出來Animation抽象類是所有補間動畫類的基類,所以基類會提供一些通用的動畫屬性方法,如下我們就來詳細看看這些屬性,關於這些屬性詳細官方解釋翻牆點選我或者翻牆點選我。
2-2-1 Animation屬性詳解
xml屬性 | java方法 | 解釋 |
---|---|---|
android:detachWallpaper | setDetachWallpaper(boolean) | 是否在桌布上執行 |
android:duration | setDuration(long) | 動畫持續時間,毫秒為單位 |
android:fillAfter | setFillAfter(boolean) | 控制元件動畫結束時是否保持動畫最後的狀態 |
android:fillBefore | setFillBefore(boolean) | 控制元件動畫結束時是否還原到開始動畫前的狀態 |
android:fillEnabled | setFillEnabled(boolean) | 與android:fillBefore效果相同 |
android:interpolator | setInterpolator(Interpolator) | 設定插值器(指定的動畫效果,譬如回彈等) |
android:repeatCount | setRepeatCount(int) | 重複次數 |
android:repeatMode | setRepeatMode(int) | 重複型別有兩個值,reverse表示倒序回放,restart表示從頭播放 |
android:startOffset | setStartOffset(long) | 呼叫start函式之後等待開始執行的時間,單位為毫秒 |
android:zAdjustment | setZAdjustment(int) | 表示被設定動畫的內容執行時在Z軸上的位置(top/bottom/normal),預設為normal |
也就是說,無論我們補間動畫的哪一種都已經具備了這種屬性,也都可以設定使用這些屬性中的一個或多個。
那接下來我們就看看每種補間動畫特有的一些屬性說明吧。
2-2-2 Alpha屬性詳解
xml屬性 | java方法 | 解釋 |
---|---|---|
android:fromAlpha | AlphaAnimation(float fromAlpha, …) | 動畫開始的透明度(0.0到1.0,0.0是全透明,1.0是不透明) |
android:toAlpha | AlphaAnimation(…, float toAlpha) | 動畫結束的透明度,同上 |
2-2-3 Rotate屬性詳解
xml屬性 | java方法 | 解釋 |
---|---|---|
android:fromDegrees | RotateAnimation(float fromDegrees, …) | 旋轉開始角度,正代表順時針度數,負代表逆時針度數 |
android:toDegrees | RotateAnimation(…, float toDegrees, …) | 旋轉結束角度,正代表順時針度數,負代表逆時針度數 |
android:pivotX | RotateAnimation(…, float pivotX, …) | 縮放起點X座標(數值、百分數、百分數p,譬如50表示以當前View左上角座標加50px為初始點、50%表示以當前View的左上角加上當前View寬高的50%做為初始點、50%p表示以當前View的左上角加上父控制元件寬高的50%做為初始點) |
android:pivotY | RotateAnimation(…, float pivotY) | 縮放起點Y座標,同上規律 |
2-2-4 Scale屬性詳解
xml屬性 | java方法 | 解釋 |
---|---|---|
android:fromXScale | ScaleAnimation(float fromX, …) | 初始X軸縮放比例,1.0表示無變化 |
android:toXScale | ScaleAnimation(…, float toX, …) | 結束X軸縮放比例 |
android:fromYScale | ScaleAnimation(…, float fromY, …) | 初始Y軸縮放比例 |
android:toYScale | ScaleAnimation(…, float toY, …) | 結束Y軸縮放比例 |
android:pivotX | ScaleAnimation(…, float pivotX, …) | 縮放起點X軸座標(數值、百分數、百分數p,譬如50表示以當前View左上角座標加50px為初始點、50%表示以當前View的左上角加上當前View寬高的50%做為初始點、50%p表示以當前View的左上角加上父控制元件寬高的50%做為初始點) |
android:pivotY | ScaleAnimation(…, float pivotY) | 縮放起點Y軸座標,同上規律 |
2-2-5 Translate屬性詳解
xml屬性 | java方法 | 解釋 |
---|---|---|
android:fromXDelta | TranslateAnimation(float fromXDelta, …) | 起始點X軸座標(數值、百分數、百分數p,譬如50表示以當前View左上角座標加50px為初始點、50%表示以當前View的左上角加上當前View寬高的50%做為初始點、50%p表示以當前View的左上角加上父控制元件寬高的50%做為初始點) |
android:fromYDelta | TranslateAnimation(…, float fromYDelta, …) | 起始點Y軸從標,同上規律 |
android:toXDelta | TranslateAnimation(…, float toXDelta, …) | 結束點X軸座標,同上規律 |
android:toYDelta | TranslateAnimation(…, float toYDelta) | 結束點Y軸座標,同上規律 |
2-2-6 AnimationSet詳解
AnimationSet繼承自Animation,是上面四種的組合容器管理類,沒有自己特有的屬性,他的屬性繼承自Animation,所以特別注意,當我們對set標籤使用Animation的屬性時會對該標籤下的所有子控制元件都產生影響。
2-3 檢視動畫使用方法
通過上面對於動畫的屬性介紹之後我們來看看在Android中這些動畫如何使用(PS:這裡直接演示xml方式,至於Java方式太簡單了就不說了),如下:
- <?xml version="1.0" encoding="utf-8"?>
- <set xmlns:android="http://schemas.android.com/apk/res/android"
- android:interpolator="@[package:]anim/interpolator_resource"
- android:shareInterpolator=["true" | "false"] >
- <alpha
- android:fromAlpha="float"
- android:toAlpha="float" />
- <scale
- android:fromXScale="float"
- android:toXScale="float"
- android:fromYScale="float"
- android:toYScale="float"
- android:pivotX="float"
- android:pivotY="float" />
- <translate
- android:fromXDelta="float"
- android:toXDelta="float"
- android:fromYDelta="float"
- android:toYDelta="float" />
- <rotate
- android:fromDegrees="float"
- android:toDegrees="float"
- android:pivotX="float"
- android:pivotY="float" />
- <set>
- ...
- </set>
- </set>
- ImageView spaceshipImage = (ImageView) findViewById(R.id.spaceshipImage);
- Animation hyperspaceJumpAnimation = AnimationUtils.loadAnimation(this, R.anim.hyperspace_jump);
- spaceshipImage.startAnimation(hyperspaceJumpAnimation);
上面就是一個標準的使用我們定義的補間動畫的模板。至於補間動畫的使用,Animation還有如下一些比較實用的方法介紹:
Animation類的方法 | 解釋 |
---|---|
reset() | 重置Animation的初始化 |
cancel() | 取消Animation動畫 |
start() | 開始Animation動畫 |
setAnimationListener(AnimationListener listener) | 給當前Animation設定動畫監聽 |
hasStarted() | 判斷當前Animation是否開始 |
hasEnded() | 判斷當前Animation是否結束 |
既然補間動畫只能給View使用,那就來看看View中和動畫相關的幾個常用方法吧,如下:
View類的常用動畫操作方法 | 解釋 |
---|---|
startAnimation(Animation animation) | 對當前View開始設定的Animation動畫 |
clearAnimation() | 取消當View在執行的Animation動畫 |
到此整個Android的補間動畫常用詳細屬性及方法全部介紹完畢,如有特殊的屬性需求可以訪問Android Developer查閱即可。如下我們就來個綜合大演練。
2-4 檢視動畫注意事項
關於檢視動畫(補間動畫)的例子我就不介紹了,網上簡直多的都氾濫了。只是強調在使用補間動畫時注意如下一點即可:
特別特別注意:補間動畫執行之後並未改變View的真實佈局屬性值。切記這一點,譬如我們在Activity中有一個Button在螢幕上方,我們設定了平移動畫移動到螢幕下方然後保持動畫最後執行狀態呆在螢幕下方,這時如果點選螢幕下方動畫執行之後的Button是沒有任何反應的,而點選原來螢幕上方沒有Button的地方卻響應的是點選Button的事件。
2-5 檢視動畫Interpolator插值器詳解
2-5-1 插值器簡介
介紹補間動畫插值器之前我們先來看一幅圖,如下:
可以看見其實各種插值器都是實現了Interpolator介面而已,同時可以看見系統提供了許多已經實現OK的插值器,具體如下:
java類 | xml id值 | 描述 |
---|---|---|
AccelerateDecelerateInterpolator | @android:anim/accelerate_decelerate_interpolator | 動畫始末速率較慢,中間加速 |
AccelerateInterpolator | @android:anim/accelerate_interpolator | 動畫開始速率較慢,之後慢慢加速 |
AnticipateInterpolator | @android:anim/anticipate_interpolator | 開始的時候從後向前甩 |
AnticipateOvershootInterpolator | @android:anim/anticipate_overshoot_interpolator | 類似上面AnticipateInterpolator |
BounceInterpolator | @android:anim/bounce_interpolator | 動畫結束時彈起 |
CycleInterpolator | @android:anim/cycle_interpolator | 迴圈播放速率改變為正弦曲線 |
DecelerateInterpolator | @android:anim/decelerate_interpolator | 動畫開始快然後慢 |
LinearInterpolator | @android:anim/linear_interpolator | 動畫勻速改變 |
OvershootInterpolator | @android:anim/overshoot_interpolator | 向前彈出一定值之後回到原來位置 |
如上就是系統提供的一些插值器,下面我們來看看怎麼使用他們。
2-5-2 插值器使用方法
插值器的使用比較簡答,如下:
- <set android:interpolator="@android:anim/accelerate_interpolator">
- ...
- </set>
2-5-3 插值器的自定義
有時候你會發現系統提供的插值器不夠用,可能就像View一樣需要自定義。所以接下來我們來看看插值器的自定義,關於插值器的自定義分為兩種實現方式,xml自定義實現(其實就是對現有的插值器的一些屬性修改)或者java程式碼實現方式。如下我們來說說。
先看看XML自定義插值器的步驟:
- 在res/anim/目錄下建立filename.xml檔案。
- 修改你準備自定義的插值器如下:
- <?xml version="1.0" encoding="utf-8"?>
- <InterpolatorName xmlns:android="http://schemas.android.com/apk/res/android"
- android:attribute_name="value"
- />
- 在你的補間動畫檔案中引用該檔案即可。
可以看見上面第二步修改的是現有插值器的一些屬性,但是有些插值器卻不具備修改屬性,具體如下:
<accelerateDecelerateInterpolator>
無可自定義的attribute。
<accelerateInterpolator>
android:factor 浮點值,加速速率(預設值為1)。
<anticipateInterploator>
android:tension 浮點值,起始點後拉的張力數(預設值為2)。
<anticipateOvershootInterpolator>
android:tension 浮點值,起始點後拉的張力數(預設值為2)。
android:extraTension 浮點值,拉力的倍數(預設值為1.5)。
<bounceInterpolator>
無可自定義的attribute。
<cycleInterplolator>
android:cycles 整形,迴圈的個數(預設為1)。
<decelerateInterpolator>
android:factor 浮點值,減速的速率(預設為1)。
<linearInterpolator>
無可自定義的attribute。
<overshootInterpolator>
android:tension 浮點值,超出終點後的張力(預設為2)。
再來看看Java自定義插值器的(Java自定義插值器其實是xml自定義的升級,也就是說如果我們修改xml的屬性還不能滿足需求,那就可以選擇通過Java來實現)方式。
可以看見上面所有的Interpolator都實現了Interpolator介面,而Interpolator介面又繼承自TimeInterpolator,TimeInterpolator介面定義了一個float getInterpolation(float input);方法,這個方法是由系統呼叫的,其中的引數input代表動畫的時間,在0和1之間,也就是開始和結束之間。
如下就是一個動畫始末速率較慢、中間加速的AccelerateDecelerateInterpolator插值器:
- public class AccelerateDecelerateInterpolator extends BaseInterpolator
- implements NativeInterpolatorFactory {
- ......
- public float getInterpolation(float input) {
- return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
- }
- ......
- }
到此整個補間動畫與補間動畫的插值器都分析完畢了,接下來看下別的動畫。
3 Drawable Animation(Drawable動畫)使用詳解
3-1 Drawable動畫概述
Drawable動畫其實就是Frame動畫(幀動畫),它允許你實現像播放幻燈片一樣的效果,這種動畫的實質其實是Drawable,所以這種動畫的XML定義方式檔案一般放在res/drawable/目錄下。具體關於幀動畫的xml使用方式翻牆點選我檢視,java方式翻牆點選我檢視。
如下圖就是幀動畫的原始碼檔案:
可以看見實際的真實父類就是Drawable。
3-2 Drawable動畫詳細說明
我們依舊可以使用xml或者java方式實現幀動畫。但是依舊推薦使用xml,具體如下:
<animation-list>
必須是根節點,包含一個或者多個<item>
元素,屬性有:
- android:oneshot true代表只執行一次,false迴圈執行。
<item>
類似一幀的動畫資源。
<item>
animation-list的子項,包含屬性如下:
- android:drawable 一個frame的Drawable資源。
- android:duration 一個frame顯示多長時間。
3-3 Drawable動畫例項演示
關於幀動畫相對來說比較簡單,這裡給出一個常規使用框架,如下:
- <!-- 注意:rocket.xml檔案位於res/drawable/目錄下 -->
- <?xml version="1.0" encoding="utf-8"?>
- <animation-list xmlns:android="http://schemas.android.com/apk/res/android"
- android:oneshot=["true" | "false"] >
- <item
- android:drawable="@[package:]drawable/drawable_resource_name"
- android:duration="integer" />
- </animation-list>
- ImageView rocketImage = (ImageView) findViewById(R.id.rocket_image);
- rocketImage.setBackgroundResource(R.drawable.rocket_thrust);
- rocketAnimation = (AnimationDrawable) rocketImage.getBackground();
- rocketAnimation.start();
特別注意,AnimationDrawable的start()方法不能在Activity的onCreate方法中調運,因為AnimationDrawable還未完全附著到window上,所以最好的調運時機是onWindowFocusChanged()方法中。
至此幀動畫也就說明完成了。讓我們接下來進入Android更牛叉的動畫型別。
4 Property Animation(屬性動畫)使用詳解
在使用屬性動畫之前先來看幾個常用的View屬性成員:
- translationX,translationY:控制View的位置,值是相對於View容器左上角座標的偏移。
- rotationX,rotationY:控制相對於軸心旋轉。
- x,y:控制View在容器中的位置,即左上角座標加上translationX和translationY的值。
- alpha:控制View物件的alpha透明度值。
這幾個常用的屬性相信大家都很熟悉,接下來的屬性動畫我們就從這裡展開。
4-1 屬性動畫概述
Android 3.0以後引入了屬性動畫,屬性動畫可以輕而易舉的實現許多View動畫做不到的事,上面也看見了,View動畫無非也就做那幾種事情,別的也搞不定,而屬性動畫就可以的,譬如3D旋轉一張圖片。其實說白了,你記住一點就行,屬性動畫實現原理就是修改控制元件的屬性值實現的動畫。
具體先看下類關係:
- /**
- * This is the superclass for classes which provide basic support for animations which can be
- * started, ended, and have <code>AnimatorListeners</code> added to them.
- */
- public abstract class Animator implements Cloneable {
- ......
- }
所有的屬性動畫的抽象基類就是他。我們看下他的實現子類:
其實可以看見,屬性動畫的實現有7個類(PS,之所以類繼承關係列表會出來那麼多是因為我下載了所有版本的SDK,你只用關注我紅點標註的就行,妹的,ubuntu下圖片處理工具怎麼都這麼難用),進去粗略分析可以發現,好幾個是hide的類,而其他可用的類繼承關係又如下:
java類名 | xml關鍵字 | 描述資訊 |
---|---|---|
ValueAnimator | <animator> 放置在res/animator/目錄下 |
在一個特定的時間裡執行一個動畫 |
TimeAnimator | 時序監聽回撥工具 | |
ObjectAnimator | <objectAnimator> 放置在res/animator/目錄下 |
一個物件的一個屬性動畫 |
AnimatorSet | <set> 放置在res/animator/目錄下 |
動畫集合 |
所以可以看見,我們平時使用屬性動畫的重點就在於AnimatorSet、ObjectAnimator、TimeAnimator、ValueAnimator。所以接下來我們就來依次說說如何使用。
4-2 屬性動畫詳細說明
4-2-1 屬性動畫計算原理
Android屬性動畫(注意最低相容版本,不過可以使用開源專案來替代低版本問題)提供了以下屬性:
- Duration:動畫的持續時間;
- TimeInterpolation:定義動畫變化速率的介面,所有插值器都必須實現此介面,如線性、非線性插值器;
- TypeEvaluator:用於定義屬性值計算方式的介面,有int、float、color型別,根據屬性的起始、結束值和插值一起計算出當前時間的屬性值;
- Animation sets:動畫集合,即可以同時對一個物件應用多個動畫,這些動畫可以同時播放也可以對不同動畫設定不同的延遲;
- Frame refreash delay:多少時間重新整理一次,即每隔多少時間計算一次屬性值,預設為10ms,最終重新整理時間還受系統程序排程與硬體的影響;
- Repeat Country and behavoir:重複次數與方式,如播放3次、5次、無限迴圈,可以讓此動畫一直重複,或播放完時向反向播放;
接下來先來看官方為了解釋原理給出的兩幅圖(其實就是初中物理題,不解釋):
上面就是一個線性勻速動畫,描述了一個Object的X屬性運動動畫,該物件的X座標在40ms內從0移動到40,每10ms重新整理一次,移動4次,每次移動為40/4=10pixel。
上面是一個非勻速動畫,描述了一個Object的X屬性運動動畫,該物件的X座標在40ms內從0移動到40,每10ms重新整理一次,移動4次,但是速率不同,開始和結束的速度要比中間部分慢,即先加速後減速。
接下來我們來詳細的看一下,屬性動畫系統的重要組成部分是如何計算動畫值的,下圖描述瞭如上面所示動畫的實現作用過程。
其中的ValueAnimator是動畫的執行類,跟蹤了當前動畫的執行時間和當前時間下的屬性值;ValueAnimator封裝了動畫的TimeInterpolator時間插值器和一個TypeEvaluator型別估值,用於設定動畫屬性的值,就像上面圖2非線性動畫裡,TimeInterpolator使用了AccelerateDecelerateInterpolator、TypeEvaluator使用了IntEvaluator。
為了執行一個動畫,你需要建立一個ValueAnimator,並且指定目標物件屬性的開始、結束值和持續時間。在呼叫start後,整個動畫過程中, ValueAnimator會根據已經完成的動畫時間計算得到一個0到1之間的分數,代表該動畫的已完成動畫百分比。0表示0%,1表示100%,譬如上面圖一線性勻速動畫中總時間 t = 40 ms,t = 10 ms的時候是 0.25。
當ValueAnimator計算完已完成動畫分數後,它會呼叫當前設定的TimeInterpolator,去計算得到一個interpolated(插值)分數,在計算過程中,已完成動畫百分比會被加入到新的插值計算中。如上圖2非線性動畫中,因為動畫的運動是緩慢加速的,它的插值分數大約是 0.15,小於t = 10ms時的已完成動畫分數0.25。而在上圖1中,這個插值分數一直和已完成動畫分數是相同的。
當插值分數計算完成後,ValueAnimator會根據插值分數呼叫合適的 TypeEvaluator去計算運動中的屬性值。
好了,現在我們來看下程式碼就明白這段話了,上面圖2非線性動畫裡,TimeInterpolator使用了AccelerateDecelerateInterpolator、TypeEvaluator使用了IntEvaluator。所以這些類都是標準的API,我們來看下標準API就能類比自己寫了,如下:
首先計算已完成動畫時間分數(以10ms為例):t=10ms/40ms=0.25。
接著看如下原始碼如何實現計算差值分數的:
- public class AccelerateDecelerateInterpolator extends BaseInterpolator
- implements NativeInterpolatorFactory {
- public AccelerateDecelerateInterpolator() {
- }
- ......
- //這是我們關注重點,可以發現如下計算公式計算後(input即為時間因子)插值大約為0.15。
- public float getInterpolation(float input) {
- return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
- }
- ......
- }
其實AccelerateDecelerateInterpolator的基類介面就是TimeInterpolator,如下,他只有getInterpolation方法,也就是上面我們關注的方法。
- public interface TimeInterpolator {
- float getInterpolation(float input);
- }
接著ValueAnimator會根據插值分數呼叫合適的TypeEvaluator(IntEvaluator)去計算運動中的屬性值,如下,因為startValue = 0,所以屬性值:0+0.15*(40-0)= 6。
- public class IntEvaluator implements TypeEvaluator<Integer> {
- public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
- int startInt = startValue;
- return (int)(startInt + fraction * (endValue - startInt));
- }
- }
這就是官方給的一個關於屬性動畫實現的過程及基本原理解釋,相信你看到這裡是會有些迷糊的,沒關係,你先有個大致概念就行,接下來我們會慢慢進入實戰,因為Android的屬性動畫相對於其他動畫來說涉及的知識點本來就比較複雜,所以我們慢慢來。
4-2-2 XML方式屬性動畫
在xml中可直接用的屬性動畫節點有ValueAnimator、ObjectAnimator、AnimatorSet。如下是官方的一個例子和解釋(詳情點我):
- <set
- android:ordering=["together" | "sequentially"]>
- <objectAnimator
- android:propertyName="string"
- android:duration="int"
- android:valueFrom="float | int | color"
- android:valueTo="float | int | color"
- android:startOffset="int"
- android:repeatCount="int"
- android:repeatMode=["repeat" | "reverse"]
- android:valueType=["intType" | "floatType"]/>
- <animator
- android:duration="int"
- android:valueFrom="float | int | color"
- android:valueTo="float | int | color"
- android:startOffset="int"
- android:repeatCount="int"
- android:repeatMode=["repeat" | "reverse"]
- android:valueType=["intType" | "floatType"]/>
- <set>
- ...
- </set>
- </set>
<set>
屬性解釋:
xml屬性 | 解釋 |
---|---|
android:ordering | 控制子動畫啟動方式是先後有序的還是同時進行。sequentially:動畫按照先後順序;together(預設):動畫同時啟動; |
<objectAnimator>
屬性解釋:
xml屬性 | 解釋 |
---|---|
android:propertyName | String型別,必須要設定的節點屬性,代表要執行動畫的屬性(通過名字引用),闢如你可以指定了一個View的”alpha” 或者 “backgroundColor” ,這個objectAnimator元素沒有對外說明target屬性,所以你不能在XML中設定執行這個動畫,必須通過呼叫loadAnimator()方法載入你的XML動畫資源,然後呼叫setTarget()應用到具備這個屬性的目標物件上(譬如TextView)。 |
android:valueTo | float、int或者color型別,必須要設定的節點屬性,表明動畫結束的點;如果是顏色的話,由6位十六進位制的數字表示。 |
android:valueFrom | 相對應valueTo,動畫的起始點,如果沒有指定,系統會通過屬性的get方法獲取,顏色也是6位十六進位制的數字表示。 |
android:duration | 動畫的時長,int型別,以毫秒為單位,預設為300毫秒。 |
android:startOffset | 動畫延遲的時間,從呼叫start方法後開始計算,int型,毫秒為單位。 |
android:repeatCount | 一個動畫的重複次數,int型,”-1“表示無限迴圈,”1“表示動畫在第一次執行完成後重複執行一次,也就是兩次,預設為0,不重複執行。 |
android:repeatMode | 重複模式:int型,當一個動畫執行完的時候應該如何處理。該值必須是正數或者是-1,“reverse”會使得按照動畫向相反的方向執行,可實現類似鐘擺效果。“repeat”會使得動畫每次都從頭開始迴圈。 |
android:valueType | 關鍵引數,如果該value是一個顏色,那麼就不需要指定,因為動畫框架會自動的處理顏色值。有intType和floatType(預設)兩種:分別說明動畫值為int和float型。 |
<objectAnimator>
屬性解釋:
同上<objectAnimator>
屬性,不多介紹。
XML屬性動畫使用方法:
- AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext,
- R.animtor.property_animator);
- set.setTarget(myObject);
- set.start();
4-2-3 Java方式屬性動畫
1、ObjectAnimator:繼承自ValueAnimator,允許你指定要進行動畫的物件以及該物件的一個屬性。該類會根據計算得到的新值自動更新屬性。大多數的情況使用ObjectAnimator就足夠了,因為它使得目標物件動畫值的處理過程變得足夠簡單,不用像ValueAnimator那樣自己寫動畫更新的邏輯,但是ObjectAnimator有一定的限制,比如它需要目標物件的屬性提供指定的處理方法(譬如提供getXXX,setXXX方法),這時候你就需要根據自己的需求在ObjectAnimator和ValueAnimator中看哪種實現更方便了。
ObjectAnimator類提供了ofInt、ofFloat、ofObject這個三個常用的方法,這些方法都是設定動畫作用的元素、屬性、開始、結束等任意屬性值。當屬性值(上面方法的引數)只設置一個時就把通過getXXX反射獲取的值作為起點,設定的值作為終點;如果設定兩個(引數),那麼一個是開始、另一個是結束。
特別注意:ObjectAnimator的動畫原理是不停的呼叫setXXX方法更新屬性值,所有使用ObjectAnimator更新屬性時的前提是Object必須宣告有getXXX和setXXX方法。
我們通常使用ObjectAnimator設定View已知的屬性來生成動畫,而一般View已知屬性變化時都會主動觸發重繪圖操作,所以動畫會自動實現;但是也有特殊情況,譬如作用Object不是View,或者作用的屬性沒有觸發重繪,或者我們在重繪時需要做自己的操作,那都可以通過如下方法手動設定:
- ObjectAnimator mObjectAnimator= ObjectAnimator.ofInt(view, "customerDefineAnyThingName", 0, 1).setDuration(2000);
- mObjectAnimator.addUpdateListener(new AnimatorUpdateListener()
- {
- @Override
- public void onAnimationUpdate(ValueAnimator animation)
- {
- //int value = animation.getAnimatedValue(); 可以獲取當前屬性值
- //view.postInvalidate(); 可以主動重新整理
- //view.setXXX(value);
- //view.setXXX(value);
- //......可以批量修改屬性
- }
- });
如下是一個我在專案中的Y軸3D旋轉動畫實現例項:
- ObjectAnimator.ofFloat(view, "rotationY", 0.0f, 360.0f).setDuration(1000).start();
2、PropertyValuesHolder:多屬性動畫同時工作管理類。有時候我們需要同時修改多個屬性,那就可以用到此類,具體如下:
- PropertyValuesHolder a1 = PropertyValuesHolder.ofFloat("alpha", 0f, 1f);
- PropertyValuesHolder a2 = PropertyValuesHolder.ofFloat("translationY", 0, viewWidth);
- ......
- ObjectAnimator.ofPropertyValuesHolder(view, a1, a2, ......).setDuration(1000).start();
如上程式碼就可以實現同時修改多個屬性的動畫啦。
3、ValueAnimator:屬性動畫中的時間驅動,管理著動畫時間的開始、結束屬性值,相應時間屬性值計算方法等。包含所有計算動畫值的核心函式以及每一個動畫時間節點上的資訊、一個動畫是否重複、是否監聽更新事件等,並且還可以設定自定義的計算型別。
特別注意:ValueAnimator只是動畫計算管理驅動,設定了作用目標,但沒有設定屬性,需要通過updateListener裡設定屬性才會生效。
- ValueAnimator animator = ValueAnimator.ofFloat(0, mContentHeight); //定義動畫
- animator.setTarget(view); //設定作用目標
- animator.setDuration(5000).start();
- animator.addUpdateListener(new AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation){
- float value = (float) animation.getAnimatedValue();
- view.setXXX(value); //必須通過這裡設定屬性值才有效
- view.mXXX = value; //不需要setXXX屬性方法
- }
- });
大眼看上去可以發現和ObjectAnimator沒啥區別,實際上正是由於ValueAnimator不直接操作屬性值,所以要操作物件的屬性可以不需要setXXX與getXXX方法,你完全可以通過當前動畫的計算去修改任何屬性。
4、AnimationSet:動畫集合,提供把多個動畫組合成一個組合的機制,並可設定動畫的時序關係,如同時播放、順序播放或延遲播放。具體使用方法比較簡單,如下:
- ObjectAnimator a1 = ObjectAnimator.ofFloat(view, "alpha", 1.0f, 0f);
- ObjectAnimator a2 = ObjectAnimator.ofFloat(view, "translationY", 0f, viewWidth);
- ......
- AnimatorSet animSet = new AnimatorSet();
- animSet.setDuration(5000);
- animSet.setInterpolator(new LinearInterpolator());
- //animSet.playTogether(a1, a2, ...); //兩個動畫同時執行
- animSet.play(a1).after(a2); //先後執行
- ......//其他組合方式
- animSet.start();
5、Evaluators相關類解釋: Evaluators就是屬性動畫系統如何去計算一個屬性值。它們通過Animator提供的動畫的起始和結束值去計算一個動畫的屬性值。
-
IntEvaluator:整數屬性值。
-
FloatEvaluator:浮點數屬性值。
-
ArgbEvaluator:十六進位制color屬性值。
-
TypeEvaluator:使用者自定義屬性值介面,譬如物件屬性值型別不是int、float、color型別,你必須實現這個介面去定義自己的資料型別。
既然說到這了,那就來個例子吧,譬如我們需要實現一個自定義屬性型別和計算規則的屬性動畫,如下型別float[]:
- ValueAnimator valueAnimator = new ValueAnimator();
- valueAnimator.setDuration(5000);
- valueAnimator.setObjectValues(new float[2]); //設定屬性值型別
- valueAnimator.setInterpolator(new LinearInterpolator()); <