Android 平臺提供了一套完整的動畫框架,使得應用開發者能夠用它來實現各類動畫效果。好比:按扭的彈入彈出效果、Activity的切換動畫、文本圖片的旋轉效果等。Android平臺的動畫分三個部分,在Android3.0版本之前支持兩種動畫,分別爲補間動畫(Tween Animation)和逐幀動畫(FrameAnimation);在Android 3.0版本中新加入的動畫叫屬性動畫(Property Animation)。下面分別介紹這三種動畫。android
1、Tween 動畫:Tween 動畫是經過對場景中的對象不斷作圖像變換 ( 平移、縮放、旋轉、改變透明度) 產生動畫效果,可是該動畫只能應用於View對象,而且只支持一部分屬性,如支持縮放旋轉而不支持背景顏色的改變。該動畫實現方式其實就是預先定義一組指令,這些指令指定了圖形變換的類型、觸發時間、持續時間。這些指令能夠是以 XML 文件方式定義,也能夠是以源代碼方式定義。程序沿着時間線執行這些指令就能夠實現動畫效果。下面首先說明如何用XML來定Tween 動畫:canvas
一、使用XML來定義Tween Animation, 動畫的XML文件在工程中res/anim目錄,這個文件必須包含一個根元素,可使<alpha><scale> <translate> <rotate>插值元素或者是把上面的元素都放入<set>元素組中,默認狀況下,因此的動畫指令都是同時發生的,爲了讓他們按序列發生,須要設置一個特殊的屬性startOffset。動畫的指令定義了你想要發生什麼樣的轉換,當他們發生了,應該執行多長時間,轉換能夠是連續的也可使同時的。例如,你讓文本內容從左邊移動到右邊,而後旋轉180度,或者在移動的過程當中同時旋轉,沒個轉換須要設置一些特殊的參數(開始和結束的大小尺寸的大小變化,開始和結束的旋轉角度等等,也能夠設置些基本的參數(例如,開始時間與週期),若是讓幾個轉換同時發生,能夠給它們設置相同的開始時間,若是按序列的話,計算開始時間加上其週期。關於如何使用XML來定義見以下代碼:app
- <?xml version="1.0" encoding="UTF-8"?>
- <set xmlns:android="http://schemas.android.com/apk/res/android">
- <!--
- Tween Animation:經過對場景裏的對象不斷作圖像變換(平移、縮放、旋轉)產生動畫效
- Alpha:漸變透明度動畫效果
- Scale:漸變尺寸伸縮動畫效果
- Translate:畫面轉換位置移動動畫效果
- Rotate:畫面旋轉動畫效果
- Tween Animation 通用屬性[類型] 功能
- Duration[long] 屬性爲動畫持續時間 時間以毫秒爲單位
- fillAfter [boolean] 當設置爲true ,該動畫轉化在動畫結束後被應用
- fillBefore[boolean] 當設置爲true ,該動畫轉化在動畫開始前被應用
- interpolator 指定一個動畫的插入器 有一些常見的插入器
- accelerate_decelerate_interpolator
- 加速-減速 動畫插入器
- accelerate_interpolator
- 加速-動畫插入器
- decelerate_interpolator
- 減速- 動畫插入器
- 其餘的屬於特定的動畫效果
- repeatCount[int] 動畫的重複次數
- RepeatMode[int] 定義重複的行爲 1:從新開始 2:plays backward
- startOffset[long] 動畫之間的時間間隔,從上次動畫停多少時間開始執行下個動畫
- zAdjustment[int] 定義動畫的Z Order的改變 0:保持Z Order不變
- 1:保持在最上層
- -1:保持在最下層
- -->
- <!--
- 透明控制動畫
- -->
- <alpha
- android:fromAlpha="0.1"
- android:toAlpha="1.0"
- android:duration="3000"
- />
- <!-- 尺寸伸縮動畫效果 scale
- 屬性:interpolator 指定一個動畫的插入器
- 有三種動畫插入器:
- accelerate_decelerate_interpolator 加速-減速 動畫插入器
- accelerate_interpolator 加速-動畫插入器
- decelerate_interpolator 減速- 動畫插入器
- 其餘的屬於特定的動畫效果
- fromXScale 屬性爲動畫起始時 X座標上的伸縮尺寸
- toXScale 屬性爲動畫結束時 X座標上的伸縮尺寸
- fromYScale 屬性爲動畫起始時Y座標上的伸縮尺寸
- toYScale 屬性爲動畫結束時Y座標上的伸縮尺寸
- 說明:
- 以上四種屬性值
- 0.0表示收縮到沒有
- 1.0表示正常無伸縮
- 值小於1.0表示收縮
- 值大於1.0表示放大
- pivotX 屬性爲動畫相對於物件的X座標的開始位置
- pivotY 屬性爲動畫相對於物件的Y座標的開始位置
- 說明:
- 以上兩個屬性值 從0%-100%中取值
- 50%爲物件的X或Y方向座標上的中點位置
- 長整型值:
- duration 屬性爲動畫持續時間
- 說明: 時間以毫秒爲單位
- 布爾型值:
- fillAfter 屬性 當設置爲true ,該動畫轉化在動畫結束後被應用
- -->
- <scale
- android:interpolator="@android:anim/accelerate_decelerate_interpolator"
- android:repeatCount="1"
- android:fromXScale="0.5"
- android:fromYScale="0.5"
- android:toXScale="1.4"
- android:toYScale="1.4"
- android:pivotX="50%"
- android:pivotY="50%"
- android:fillAfter="false"
- android:duration="3000"
- />
- <!--
- 畫面轉換位置移動動畫效果 translate
- fromXDelta toXDelta 爲動畫、結束起始時 X座標上的位置
- fromYDelta toYDelta 爲動畫、結束起始時 Y座標上的位置
- -->
- <translate
- android:repeatCount="2"
- android:fromXDelta="-30"
- android:fromYDelta="-30"
- android:toXDelta="-80"
- android:toYDelta="200"
- android:duration="3000"
- />
- <!--
- 畫面轉移旋轉動畫效果 rotate
- fromDegrees 爲動畫起始時物件的角度 說明
- 當角度爲負數——表示逆時針旋轉
- 當角度爲正數——表示順時針旋轉
- (負數from——to正數:順時針旋轉)
- (負數from——to負數:逆時針旋轉)
- (正數from——to正數:順時針旋轉)
- (正數from——to負數:逆時針旋轉)
- toDegrees 屬性爲動畫結束時物件旋轉的角度 能夠大於360度
- pivotX
- pivotY 爲動畫相對於物件的X、Y座標的開始位 說明:以上兩個屬性值 從0%-100%中取值
- 50%爲物件的X或Y方向座標上的中點位置
- -->
- <rotate
- android:interpolator="@android:anim/accelerate_interpolator"
- android:repeatCount="2"
- android:fromDegrees="0"
- android:toDegrees="+270"
- android:pivotX="50%"
- android:pivotY="50%"
- android:duration="3000"
- />
- </set>
在程序中引用XML資源核心代碼以下:
- Animation mAnimation ;
- mAnimation = AnimationUtils.loadAnimation(this, R.anim.anim);
- TextView text = (TextView)findViewById(R.id.textview00);
- text.setAnimation(mAnimation);
二、在代碼中定義動畫:核心代碼以下
- private Animation myAnimation_Alpha;
- private Animation myAnimation_Scale;
- private Animation myAnimation_Translate;
- private Animation myAnimation_Rotate;
- //根據各自的構造方法來初始化一個實例對象
- myAnimation_Alpha=new AlphaAnimation(0.1f, 1.0f);
- myAnimation_Scale =new ScaleAnimation(0.0f, 1.4f, 0.0f, 1.4f,
- Animation.RELATIVE_TO_SELF, 0.5f,Animation.RELATIVE_TO_SELF, 0.5f);
- myAnimation_Translate=new TranslateAnimation(30.0f, -80.0f, 30.0f, 300.0f);
- myAnimation_Rotate=new RotateAnimation(0.0f, +350.0f,
- Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
三、下面討論下其實現原理:
Tween 動畫是創建在View的級別上的,在 View 類中有一個接口 startAnimation 來使動畫開始,startAnimation 函數會將一個 Animation類別的參數傳給 View,這個 Animation 是用來指定咱們使用的是哪一種動畫,現有的動畫有平移,縮放,旋轉以及 alpha 變換等。若是須要更復雜的效果,能夠將這些動畫組合起來,
要了解 Android 動畫是如何畫出來的,首先要了解Android 的 View 是如何組織在一塊兒,以及他們是如何畫本身的內容的。每個窗口就是一棵 View 樹,繪製整個窗口須要按順序執行如下幾個步驟:
(1)繪製背景;
(2)若是須要,保存畫布(canvas)的層爲淡入或淡出作準備;
(3)繪製 View 自己的內容,經過調用View.onDraw(canvas) 函數實現,經過這個咱們應該能看出來 onDraw 函數重載的重要性,onDraw 函數中繪製線條 / 圓 / 文字等功能會調用 Canvas 中對應的功能。下面咱們會 drawLine函數爲例進行說明;
(4)繪製本身的孩子(一般也是一個 view 系統),經過dispatchDraw(canvas) 實現,參看 ViewGroup.Java 中的代碼可知,dispatchDraw->drawChild->child.draw(canvas) 這樣的調用過程被用來保證每一個子 View 的 draw 函數都被調用,經過這種遞歸調用從而讓整個View 樹中的全部 View 的內容都獲得繪製。在調用每一個子 View 的draw 函數以前,須要繪製的 View 的繪製位置是在 Canvas 經過translate 函數調用來進行切換的,窗口中的全部 View 是共用一個 Canvas 對象
(5)若是須要,繪製淡入淡出相關的內容並恢復保存的畫布所在的層(layer)
(6)繪製修飾的內容(例如滾動條),這個可知要實現滾動條效果並不須要 ScrollView,能夠在View 中完成的。
當一個 ChildView 要重畫時,它會調用其成員函數invalidate() 函數將通知其 ParentView 這個 ChildView 要重畫,這個過程一直向上遍歷到ViewRoot,當 ViewRoot 收到這個通知後就會調用上面提到的 ViewRoot 中的 draw 函數從而完成繪製。View::onDraw() 有一個畫布參數 Canvas, 畫布顧名思義就是畫東西的地方,Android 會爲每個 View 設置好畫布,View 就能夠調用 Canvas 的方法,好比:drawText, drawBitmap, drawPath 等等去畫內容。每個 ChildView 的畫布是由其ParentView 設置的,ParentView 根據 ChildView 在其內部的佈局來調整Canvas,其中畫布的屬性之一就是定義和ChildView 相關的座標系,默認是橫軸爲 X 軸,從左至右,值逐漸增大,豎軸爲 Y 軸,從上至下,值逐漸增大 。
Android 動畫就是經過ParentView 來不斷調整 ChildView 的畫布座標系來實現的,下面以平移動畫來作示例,假設在動畫開始時 ChildView 在 ParentView 中的初始位置在 (100,200) 處,這時 ParentView 會根據這個座標來設置 ChildView 的畫布,在 ParentView的 dispatchDraw 中它發現 ChildView 有一個平移動畫,並且當前的平移位置是 (100, 200),因而它經過調用畫布的函數traslate(100, 200) 來告訴 ChildView 在這個位置開始畫,這就是動畫的第一幀。若是 ParentView 發現 ChildView 有動畫,就會不斷的調用 invalidate() 這個函數,這樣就會致使本身會不斷的重畫,就會不斷的調用 dispatchDraw 這個函數,這樣就產生了動畫的後續幀,當再次進入 dispatchDraw 時,ParentView 根據平移動畫產生出第二幀的平移位置 (500, 200),而後繼續執行上述操做,而後產生第三幀,第四幀,直到動畫播完。
用戶能夠定義本身的動畫類,只須要繼承 Animation 類,而後重載applyTransformation 這個函數。對動畫來講其行爲主要靠差值點來決定的,好比,咱們想開始動畫是逐漸加快的或者逐漸變慢的,或者先快後慢的,或者是勻速的,這些功能的實現主要是靠差值函數來實現的,Android 提供了一個 Interpolator 的基類,你要實現什麼樣的速度能夠重載其函數 getInterpolation,在 Animation 的 getTransformation 中生成差值點時,會用到這個函數。
從上面的動畫機制的分析可知某一個 View 的動畫的繪製並非由他本身完成的而是由它的父 view 完成,全部咱們要注意上面 TextView 旋轉一週的動畫示例程序中動畫的效果並非由 TextView 來繪製的,而是由它的父 View來作的。findViewById(R.id.TextView01).startAnimation(anim)這個代碼實際上是給這個 TextView 設置了一個 animation,而不是進行實際的動畫繪製,代碼以下 :
- public void startAnimation(Animationanimation) {animation.setStartTime(Animation.START_ON_FIRST_FRAME);setAnimation(animation); invalidate(); }
2、Frame 動畫:Frame 動畫是順序播放事先準備好的圖像,,相似於放電影。其實現方式比較簡單,實現過程以下:在XML中的定義方式以下:
- <animation-listxmlns:android=http://schemas.android.com/apk/res/androidandroid:oneshot="true">
- <item android:drawable="@drawable/pic1"android:duration="200" />
- <item android:drawable="@drawable/pic2"android:duration="200" />
- <item android:drawable="@drawable/pic3"android:duration="200" />
- </animation-list>
必須以<animation-list>爲根元素,以<item>表示要輪換顯示的圖片,duration屬性表示各項顯示的時間。XML文件要放在/res/drawable/目錄下。示例:
ImageView imageView = (ImageView) findViewById(R.id.imageView1);
imageView.setBackgroundResource(R.drawable.drawable
anim);
anim = (AnimationDrawable) imageView.getBackground();
anim.start();
此處要注意一點:
要用AnimationDrawable 的start()方法來啓動動畫,無論動畫是否完畢,想要第二次啓動動畫必定要先調用它的stop()方法才能夠再次啓動動畫。
3、Property動畫:Property動畫是在Android 3.0中才引進的,它更改的是對象的實際屬性,在Tween 動畫中,其改變的是View的繪製效果,真正的View的屬性保持不變,好比不管在對話中如何縮放Button的大小,Button的有效點擊區域仍是沒有應用動畫時的區域,其位置與大小都不變。而在Property 動畫中,改變的是對象的實際屬性,如Button的縮放,Button的位置與大小屬性值都改變了。並且Property 動畫不止能夠應用於View,還能夠應用於任何對象。Property 動畫只是表示一個值在一段時間內的改變,當值改變時要作什麼事情徹底是本身決定的。
在Property Animation中,能夠對動畫應用如下屬性:
Duration:動畫的持續時間
TimeInterpolation:屬性值的計算方式,如先快後慢
TypeEvaluator:根據屬性的開始、結束值與TimeInterpolation計算出的因子計算出當前時間的屬性值
Repeat Country and behavoir:重複次數與方式,如播放3次、5次、無限循環,能夠此動畫一直重複,或播放完時再反向播放
Animation sets:動畫集合,便可以同時對一個對象應用幾個動畫,這些動畫能夠同時播放也能夠對不一樣動畫設置不一樣開始偏移
Framerefreash delay:多少時間刷新一次,即每隔多少時間計算一次屬性值,默認爲10ms,最終刷新時間還受系統進程調度與硬件的影響
一、Property 動畫的工做方式
這個對象的X座標在40ms內從0移動到40 pixel.按默認的10ms刷新一次,這個對象會移動4次,每次移動40/4=10pixel。
也能夠改變屬性值的改變方法,即設置不一樣的interpolation,在下圖中運動速度先逐漸增大再逐漸減少
ValueAnimator即表示一個動畫,包含動畫的開始值,結束值,持續時間等屬性。
ValueAnimator封裝了一個TimeInterpolator,TimeInterpolator定義了屬性值在開始值與結束值之間的插值方法。
ValueAnimator還封裝了一個TypeAnimator,根據開始、結束值與TimeIniterpolator計算獲得的值計算出屬性值。
ValueAnimator根據動畫已進行的時間跟動畫總時間(duration)的比計算出一個時間因子(0~1),而後根據TimeInterpolator計算出另外一個因子,最後TypeAnimator經過這個因子計算出屬性值,如上例中10ms時:
首先計算出時間因子,即通過的時間百分比:t=10ms/40ms=0.25
經插值計算(inteplator)後的插值因子:大約爲0.15,上述例子中用了AccelerateDecelerateInterpolator,計算公式爲(input即爲時間因子):
(Math.cos((input + 1) * Math.PI) / 2.0f)+ 0.5f;
最後根據TypeEvaluator計算出在10ms時的屬性值:0.15*(40-0)=6pixel。上例中TypeEvaluator爲FloatEvaluator,計算方法爲:
- public Float evaluate(float fraction,Number startValue, Number endValue) {
- float startFloat = startValue.floatValue();
- return startFloat + fraction * (endValue.floatValue() - startFloat);
- }
參數分別爲上一步的插值因子,開始值與結束值。
二、ValueAnimator
ValueAnimator包含Property Animation動畫的全部核心功能,如動畫時間,開始、結束屬性值,相應時間屬性值計算方法等。應用Property Animation有兩個步聚:
(1)計算屬性值
(2)根據屬性值執行相應的動做,如改變對象的某一屬性。
ValuAnimiator只完成了第一步工做,若是要完成第二步,須要實現ValueAnimator.onUpdateListener接口,如:
- ValueAnimator animation =ValueAnimator.ofFloat(0f, 1f);
- animation.setDuration(1000);
- animation.addUpdateListener(newAnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- }
- });
- animation.setInterpolator(newCycleInterpolator(3));
- animation.start();
Animator.AnimatorListener中含有下面四中操做:
(1)onAnimationStart()
(2)onAnimationEnd()
(3)onAnimationRepeat()
(4)onAnimationCancel
ValueAnimator.AnimatorUpdateListener中有下面一個操做
(1)onAnimationUpdate() //經過監聽這個事件在屬性的值更新時執行相應的操做,對於ValueAnimator通常要監聽此事件執行相應的動做,否則Animation沒意義(可用於計時),在ObjectAnimator(繼承自ValueAnimator)中會自動更新屬性,如無必要沒必要監聽。在函數中會傳遞一個ValueAnimator參數,經過此參數的getAnimatedValue()取得當前動畫屬性值。
能夠繼承AnimatorListenerAdapter而不是實現AnimatorListener接口來簡化操做,這個類對AnimatorListener中的函數都定義了一個空函數體,這樣就只用定義想監聽的事件而不用實現每一個函數卻只定義一空函數體。
- ObjectAnimatoroa=ObjectAnimator.ofFloat(tv, "alpha", 0f, 1f);
- oa.setDuration(3000);
- oa.addListener(newAnimatorListenerAdapter(){
- public void on AnimationEnd(Animator animation){
- }
- });
- oa.start();
三、ObjectAnimator
ObjectAnimator繼承自ValueAnimator,要指定一個對象及該對象的一個屬性,當屬性值計算完成時自動設置爲該對象的相應屬性,即完成了Property Animation的所有兩步操做。實際應用中通常都會用ObjectAnimator來改變某一對象的某一屬性,但用ObjectAnimator有必定的限制,要想使用ObjectAnimator,應該知足如下條件:
(1)對象應該有一個setter函數:set<PropertyName>(駝峯命名法)
(2)如上面的例子中,像ofFloat之類的工場方法,第一個參數爲對象名,第二個爲屬性名,後面的參數爲可變參數,若是values…參數只設置了一個值的話,那麼會假定爲目的值,屬性值的變化範圍爲當前值到目的值,爲了得到當前值,該對象要有相應屬性的getter方法:get<PropertyName>
(3)若是有getter方法,其應返回值類型應與相應的setter方法的參數類型一致。
若是上述條件不知足,則不能用ObjectAnimator,應用ValueAnimator代替。
- tv=(TextView)findViewById(R.id.textview1);
- btn=(Button)findViewById(R.id.button1);
- btn.setOnClickListener(newOnClickListener() {
- @Override
- public voidonClick(View v) {
- ObjectAnimatoroa=ObjectAnimator.ofFloat(tv, "alpha", 0f, 1f);
- oa.setDuration(3000);
- oa.start();
- }
- });
把一個TextView的透明度在3秒內從0變至1。
根據應用動畫的對象或屬性的不一樣,可能須要在onAnimationUpdate函數中調用invalidate()函數刷新視圖。
四、經過AnimationSet應用多個動畫
AnimationSet提供了一個把多個動畫組合成一個組合的機制,並可設置組中動畫的時序關係,如同時播放,順序播放等。
如下例子同時應用5個動畫:
播放anim1;
同時播放anim2,anim3,anim4;
播放anim5。
- AnimatorSetbouncer = new AnimatorSet();
- bouncer.play(anim1).before(anim2);
- bouncer.play(anim2).with(anim3);
- bouncer.play(anim2).with(anim4)
- bouncer.play(anim5).after(amin2);
- animatorSet.start();
五、TypeEvalutors
根據屬性的開始、結束值與TimeInterpolation計算出的因子計算出當前時間的屬性值,android提供瞭如下幾個evalutor:
(1)IntEvaluator:屬性的值類型爲int;
(2)FloatEvaluator:屬性的值類型爲float;
(3)ArgbEvaluator:屬性的值類型爲十六進制顏色值;
(4)TypeEvaluator:一個接口,能夠經過實現該接口自定義Evaluator。
自定義TypeEvalutor很簡單,只須要實現一個方法,如FloatEvalutor的定義:
- publicclass FloatEvaluator implements TypeEvaluator {
- public Object evaluate(float fraction,Object startValue, Object endValue) {
- float startFloat = ((Number)startValue).floatValue();
- return startFloat + fraction *(((Number) endValue).floatValue() - startFloat);
- }
- }
根據動畫執行的時間跟應用的Interplator,會計算出一個0~1之間的因子,即evalute函數中的fraction參數,經過上述FloatEvaluator應該很好看出其意思。
六、TimeInterplator
time interplator定義了屬性值變化的方式,如線性均勻改變,開始慢而後逐漸快等。在Property Animation中是TimeInterplator,在View Animation中是Interplator,這兩個是同樣的,在3.0以前只有Interplator,3.0以後實現代碼轉移至了TimeInterplator。Interplator繼承自TimeInterplator,內部沒有任何其餘代碼。
- AccelerateInterpolator 加速,開始時慢中間加速
- DecelerateInterpolator 減速,開始時快而後減速
- AccelerateDecelerateInterolator 先加速後減速,開始結束時慢,中間加速
- AnticipateInterpolator 反向 ,先向相反方向改變一段再加速播放
- AnticipateOvershootInterpolator 反向加超越,先向相反方向改變,再加速播放,會超出目的值而後緩慢移動至目的值
- BounceInterpolator 跳躍,快到目的值時值會跳躍,如目的值100,後面的值可能依次爲85,77,70,80,90,100
- CycleIinterpolator 循環,動畫循環必定次數,值的改變爲一正弦函數:Math.sin(2 * mCycles *Math.PI * input)
- LinearInterpolator 線性,線性均勻改變
- OvershottInterpolator 超越,最後超出目的值而後緩慢改變到目的值
- TimeInterpolator 一個接口,容許你自定義interpolator,以上幾個都是實現了這個接口
七、當Layout改變時應用動畫
ViewGroup中的子元素能夠經過setVisibility使其Visible、Invisible或Gone,當有子元素可見性改變時,能夠向其應用動畫,經過LayoutTransition類應用此類動畫:
transition.setAnimator(LayoutTransition.DISAPPEARING,customDisappearingAnim);
經過setAnimator應用動畫,第一個參數表示應用的情境,能夠如下4種類型:
(1)APPEARING 當一個元素變爲Visible時對其應用的動畫
(2)CHANGE
APPEARING 當一個元素變爲Visible時,因系統要從新佈局有一些元素須要移動,這些要移動的元素應用的動畫
(3)DISAPPEARING 當一個元素變爲InVisible時對其應用的動畫
(4)CHANGE
DISAPPEARING 當一個元素變爲Gone時,因系統要從新佈局有一些元素須要移動,這些要移動的元素應用的動畫 disappearing from the container.
第二個參數爲一Animator。
mTransitioner.setStagger(LayoutTransition.CHANGE
APPEARING,30);
此函數設置動畫持續時間,參數分別爲類型與時間。
八、Keyframes
keyFrame是一個 時間/值 對,經過它能夠定義一個在特定時間的特定狀態,並且在兩個keyFrame之間能夠定義不一樣的Interpolator,就至關多個動畫的拼接,第一個動畫的結束點是第二個動畫的開始點。KeyFrame是抽象類,要經過ofInt(),ofFloat(),ofObject()得到適當的KeyFrame,而後經過PropertyValuesHolder.ofKeyframe得到PropertyValuesHolder對象,如如下例子:
- Keyframe kf0 = Keyframe.ofInt(0, 400);
- Keyframe kf1 = Keyframe.ofInt(0.25f,200);
- Keyframe kf2 = Keyframe.ofInt(0.5f,400);
- Keyframe kf4 = Keyframe.ofInt(0.75f,100);
- Keyframe kf3 = Keyframe.ofInt(1f, 500);
- PropertyValuesHolder pvhRotation =PropertyValuesHolder.ofKeyframe("width", kf0, kf1, kf2, kf4, kf3);
- ObjectAnimator rotationAnim =ObjectAnimator.ofPropertyValuesHolder(btn2, pvhRotation);
- rotationAnim.setDuration(2000);
上述代碼的意思爲:設置btn對象的width屬性值使其:
開始時 Width=400
動畫開始1/4時 Width=200
動畫開始1/2時 Width=400
動畫開始3/4時 Width=100
動畫結束時 Width=500
第一個參數爲時間百分比,第二個參數是在第一個參數的時間時的屬性值。
定義了一些Keyframe後,經過PropertyValuesHolder類的方法ofKeyframe封裝,而後經過ObjectAnimator.ofPropertyValuesHolder得到Animator。
用下面的代碼能夠實現一樣的效果:
- ObjectAnimator oa=ObjectAnimator.ofInt(btn2, "width",400,200,400,100,500);
- oa.setDuration(2000);
- oa.start();
九、Animating Views
在View Animation中,對View應用Animation並無改變View的屬性,動畫的實現是經過其Parent View實現的,在View被drawn時Parents View改變它的繪製參數,draw後再改變參數invalidate,這樣雖然View的大小或旋轉角度等改變了,但View的實際屬性沒變,因此有效區域仍是應用動畫以前的區域,好比你把一按鈕放大兩倍,但仍是放大這前的區域能夠觸發點擊事件。爲了改變這一點,在Android 3.0中給View增長了一些參數並對這些參數增長了相應的getter/setter函數(ObjectAnimator要用這些函數改變這些屬性):
translationX,translationY:轉換座標(controlwhere the View is located as a delta from its left and top coordinates whichare set by its layout container.)
rotation,rotationX,rotationY:旋轉,rotation用於2D旋轉角度,3D中用到後兩個
scaleX,scaleY:縮放
x,y:View的最終座標(utility propertiesto describe the final location of the View in its container, as a sum of theleft and top values and translationX and translationY values.)
alpha:透明度
跟位置有關的參數有3個,以X座標爲例,能夠經過getLeft(),getX(),getTranslateX()得到,如有一Button btn2,佈局時其座標爲(40,0):
- //應用動畫以前 btn2.getLeft(); //40btn2.getX(); //40btn2.getTranslationX(); //0//應用translationX動畫ObjectAnimator oa=ObjectAnimator.ofFloat(btn2,"translationX", 200);
- oa.setDuration(2000);
- oa.start();/*應用translationX動畫後
- btn2.getLeft(); //40
- btn2.getX(); //240
- btn2.getTranslationX(); //200*/ //應用X動畫,假設沒有應用以前的translationX動畫 ObjectAnimator oa=ObjectAnimator.ofFloat(btn2, "x", 200);
- oa.setDuration(2000);
- oa.start();/*應用X動畫後
- btn2.getLeft(); //40
- btn2.getX(); //200
- btn2.getTranslationX(); //160*/
不管怎樣應用動畫,原來的佈局時的位置經過getLeft()得到,保持不變;
X是View最終的位置;
translationX爲最終位置與佈局時初始位置這差。
因此若就用translationX即爲在原來基礎上移動多少,X爲最終多少
getX()的值爲getLeft()與getTranslationX()的和
對於X動畫,源代碼是這樣的:
- case X:
- info.mTranslationX = value - mView.mLeft;
- break;
- Property Animation也能夠在XML中定義
- <set> - AnimatorSet
- <animator> - ValueAnimator
- <objectAnimator> - ObjectAnimator
XML文件應放大/res/animator/中,經過如下方式應用動畫:
- AnimatorSet set = (AnimatorSet)AnimatorInflater.loadAnimator(myContext, R.anim.property_animator);
- set.setTarget(myObject);
- set.start();
十、ViewPropertyAnimator
若是須要對一個View的多個屬性進行動畫能夠用ViewPropertyAnimator類,該類對多屬性動畫進行了優化,會合並一些invalidate()來減小刷新視圖,該類在3.1中引入。
如下兩段代碼實現一樣的效果:
- PropertyValuesHolder pvhX =PropertyValuesHolder.ofFloat("x", 50f);
- PropertyValuesHolder pvhY =PropertyValuesHolder.ofFloat("y", 100f);
- ObjectAnimator.ofPropertyValuesHolder(myView,pvhX, pvyY).start();
- myView.animate().x(50f).y(100f);