Android三種常用動畫分享
在Android3.0(即API Level11)以前,Android僅支援2種動畫:分別是Frame Animation(逐幀動畫)和Tween Animation(補間動畫),在3.0之後Android支援了一種新的動畫系統,稱為:Property Animation(屬性動畫)。
一、Frame Animation:(逐幀動畫)
這個很好理解,一幀幀的播放圖片,利用人眼視覺殘留原理,給我們帶來動畫的感覺。它的原理的GIF圖片、電影播放原理一樣。
1.定義逐幀動畫比較簡單,只要在中使用子項目定義所有播放幀即可。
(1) android:oneshot 設定是否僅播放一次
(2) android:drawable 設定每一幀圖片
(3) android:duration 設定圖片間切換間隔
2.習慣上把AnimationDrawable設定為ImageView的背景
android:background=@anim/frame_anim
然後我們就可以在java代碼中擷取AnimationDrawable對象了
AnimationDrawable anim = (AnimationDrawable)imageView.getBackground();
(需要注意的是,AnimationDrawable預設是不播放的,調用其start()方法開始播放,stop停止播放)
3.上面的動畫檔案是通過xml檔案來配置的,如果你喜歡,也可以通過在java代碼中建立AnimationDrawable對象,然後通過addFrame(Drawable frame, int duration)方法向動畫添加幀,然後start()。。。
二、Tween Animation:(補間動畫)
補間動畫就是我們只需指定開始、結束的“主要畫面格“,而變化中的其他幀由系統來計算,不必自己一幀幀的去定義。
1. Android使用Animation代表抽象動畫,包括四種子類:AlphaAnimation(透明度動畫)、ScaleAnimation(縮放動畫)、TranslateAnimation(位移動畫)、RotateAnimation(透明度動畫)。Android裡面允許在java中建立Animation類對象,但是一般都會採用動畫資源檔案來定義動畫,把介面與邏輯分離
(一個set可以同時定義多個動畫,一起執行。)
2. android:interpolator=@android:anim/linear_interpolator控制動畫期間需要補入多少幀,簡單來說就是控制動畫速度,有些地方翻譯為“插值“。Interpolator有幾種實作類別:LinearInterpolator、AccelerateInterpolator、AccelerateDecelerateInterpolator、CycleInterpolator、DecelerateInterpolator,具體使用可以參考官方API Demo。
3. 定義好anim檔案後,我們可以通過AnimationUtils工具類來載入它們,載入成功後返回一個Animation。然後就可以通過View的startAnimation(anim)開始執行動畫了。
Animation anim = AnimationUtils.loadAnimation(this, R.anim.anim);//設定動畫結束後保留結束狀態anim.setFillAfter(true);//設定插值效果anim.setInterpolator(interpolator);//對view執行動畫view. startAnimation(anim);
三、Property Animation:(屬性動畫)
屬性動畫,這個是在Android 3.0中才引進的,它可以直接更改我們對象的屬性。在上面提到的Tween Animation中,只是更改View的繪畫效果而View的真實屬性是不改變的。假設你用Tween動畫將一個Button從左邊移到右邊,無論你怎麼點擊移動後的Button,他都沒有反應。而當你點擊移動前Button的位置時才有反應,因為Button的位置屬性木有改變。而Property Animation則可以直接改變View對象的屬性值,這樣可以讓我們少做一些處理工作,提高效率與代碼的可讀性。
(1)ValueAnimator:包含Property Animation動畫的所有核心功能,如動畫時間,開始、結束屬性值,相應時間屬性值計算方法等。應用ValueAnimator有兩個步驟
1計算屬性值。
2根據屬性值執行相應的動作,如改變對象的某一屬性。
我們的主是第二步,需要實現ValueAnimator.onUpdateListener介面,這個介面只有一個函數onAnimationUpdate(),將要改變View對象屬性的事情在該介面中do。
animation.addUpdateListener(new AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { //do your work }});
(2)ObjectAnimator:繼承自ValueAnimator,要指定一個對象及該對象的一個屬性,當屬性值計算完成時自動化佈建為該對象的相應屬性,即完成了Property Animation的全部兩步操作。實際應用中一般都會用ObjectAnimator來改變某一對象的某一屬性,但用ObjectAnimator有一定的限制,要想使用ObjectAnimator,應該滿足以下條件:
1.對象應該有一個setter函數:set(駝峰命名法)
2如下面的例子,像ofFloat之類的工場方法,第一個參數為對象名,第二個為屬性名稱,後面的參數為可變參數,如果values…參數只設定了一個值的話,那麼會假定為目的值,屬性值的變化範圍為當前值到目的值,為了獲得當前值,該對象要有相應屬性的getter方法:get
3如果有getter方法,其應傳回值類型應與相應的setter方法的參數類型一致。
ObjectAnimator oa=ObjectAnimator.ofFloat(tv, alpha, 0f, 1f);oa.setDuration(3000);oa.start();
如果不滿足上面的條件,我們只能乖乖的使用ValueAnimator來建立動畫。
(3)Animator.AnimatorListener:可以為Animator設定動畫監聽,需要重寫下面四個方法。
onAnimationStart()onAnimationEnd()onAnimationRepeat()onAnimationCancel()
這裡我們也可以實現AnimatorListenerAdapter,他的好處是可以只用定義想監聽的事件而不用實現每個函數卻只定義一空函數體。如下:
anim.addListener(new AnimatorListenerAdapter() { public void on AnimationEnd(Animator animation){ //do your work }});
(4)AnimationSet:可以組合多個動畫共同工作
AnimatorSet bouncer = new AnimatorSet();bouncer.play(anim1).before(anim2);bouncer.play(anim2).with(anim3);bouncer.play(anim2).with(anim4)bouncer.play(anim5).after(amin2);animatorSet.start();
上面的代碼意思是: 首先播放anim1;同時播放anim2,anim3,anim4;最後播放anim5。
(5)TimeInterplator:與Tween中的interpolator類似。有以下幾種
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,以上幾個都是實現了這個介面
(6)Keyframes:可以讓我們定義除了開始和結束以外的主要畫面格。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(btn, pvhRotation);
上述代碼的意思是:設定btn對象的width屬性值使其:開始時 Width=400,動畫開始1/4時 Width=200,動畫開始1/2時 Width=400,動畫開始3/4時 Width=100,動畫結束時 Width=500。
(7)ViewPropertyAnimator:對一個View同時改變多種屬性,非常推薦用這種。該類對多屬性動畫進行了最佳化,會合并一些invalidate()來減少重新整理視圖。而且使用起來非常簡便,但是要求API LEVEL 12,即Android 3.1以上。僅需要一行代碼即可完成水平、豎直移動
myView.animate().translationX(50f). translationY(100f);
(8)常需要改變的一些屬性:
translationX,translationY: View相對於原始位置的位移量
rotation,rotationX,rotationY: 旋轉,rotation用於2D旋轉角度,3D中用到後兩個
scaleX,scaleY: 縮放比
x,y: View的最終座標,是View的left,top位置加上translationX,translationY
alpha: 透明度
四、最後自己總結一下這三種動畫的優缺點:
(1)Frame Animation(幀動畫)主要用於播放一幀幀準備好的圖片,類似GIF圖片,優點是使用簡單方便、缺點是需要事先準備好每一幀圖片;
(2)Tween Animation(補間動畫)僅需定義開始與結束的主要畫面格,而變化的中間幀由系統補上,優點是不用準備每一幀,缺點是只改變了對象繪製,而沒有改變View本身屬性。因此如果改變了按鈕的位置,還是需要點擊原來按鈕所在位置才有效。
(3)Property Animation(屬性動畫)是3.0後推出的動畫,優點是使用簡單、降低實現的複雜度、直接更改對象的屬性、幾乎可適用於任何對象而僅非View類,缺點是需要3.0以上的API支援,限制較大!但是目前國外有個開源庫,可以提供低版本支援!