Android動畫系列——View動畫和幀動畫
Android開發中,常用的動畫有三種,View動畫,幀動畫和屬性動畫。
View動畫
View動畫也被稱為TweenAnimation,是在檢視上執行補間動畫,它作用於檢視整體。補間動畫指的是隻要指定動畫開始和結束時刻的“關鍵幀”,而動畫變化過程的“中間幀”由系統計算並補齊。無論動畫如何改變檢視的顯示區域,檢視原來的邊界也不會自動調整(縮放)來適應檢視動畫的顯示區域。那麼就可以這樣理解:檢視通過ScaleAnimation或者TranslateAnimation動畫,使顯示區域超過了檢視原有的邊界,檢視不會被剪裁。與之相反的是,當檢視的動畫超過父容器的邊界時,顯示區域將被剪裁。
系統提供的View動畫有且只有4種:TranslateAnimation(平移動畫)、AlphaAnimation(透明度動畫)、ScaleAnimation(縮放動畫)、Rotation(旋轉動畫)。他們都是以Animation類的派生類。具體的相關類的繼承圖如下:

Animation的派生類
AnimationSet是動畫集合類,可以將多個不同的XxxAnimation組合,形成一組複雜效果的View動畫。
使用View動畫主要有兩種方式,xml定義和程式碼定義:
先看看xml定義,首先在res/anim目錄下定義一個xml檔案
<set xmlns:android="http://schemas.android.com/apk/res/android" > <translate android:duration="2000" android:fromXDelta="0" android:fromYDelta="0" android:toXDelta="0" android:toYDelta="200" /> </set>
然後通過AnimationUtils載入xml中的動畫,生成Animation物件
TranslateAnimation translateAnimation = AnimationUtils.loadAnimation(context,R.anim.anim_translate); intentBtn.startAnimation(translateAnimation);
最後呼叫檢視的startAnimation方法給檢視設定動畫並開始。
再來看看在程式碼中定義:
TranslateAnimation translateAnimation = new TranslateAnimation(0f, 0f, 0f, 200f); translateAnimation.setDuration(1000);//動畫的持續時間,單位毫秒 translateAnimation.setFillAfter(true);//引數為true表示動畫結束後View停留在結束位置 intentBtn.startAnimation(translateAnimation);
上面的程式碼是簡單的Animation動畫的使用方式,其中值得一提的是,setFillAfter(true)方法,引數為true,表示動畫結束後,檢視停留在完成時的位置;引數為false(預設),表示動畫結束後,檢視還原到起始位置。
我們還可以給Animation設定監聽事件,監聽動畫的開始和結束
translateAnimation.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { //動畫開始時呼叫 } @Override public void onAnimationEnd(Animation animation) { //動畫結束時呼叫 } @Override public void onAnimationRepeat(Animation animation) { //動畫重複播放時呼叫 } });
View動畫的兩個常用的特殊場景
- ViewGroup子檢視的佈局動畫(LayoutAnimation)。以ListView為例:
//然後在程式碼中,給ListView設定動畫(LayoutAnimation) LayoutAnimationController lac=new LayoutAnimationController(AnimationUtils.loadAnimation(this, R.anim.zoom_in)); lac.setDelay(0.5f); lac.setOrder(LayoutAnimationController.ORDER_RANDOM); mListView.setLayoutAnimation(lac); //也可以layout檔案中給ListView設定layoutAnimation屬性 <ListView android:id="@+id/listView" android:layoutAnimation="@anim/anim_layout" android:layout_width="match_parent" android:layout_height="match_parent" > </ListView>
layoutAnimation雖然是API 1中就已經引入,但只能在ViewGroup初次建立時才能使用指定動畫。容器建立以後,再往ViewGroup里加Item就不會再有動畫。在API 11之後,Android為了支援ViewGroup類控制元件,在新增和移除其中控制元件時自動新增動畫,為我們提供了一個非常簡單的屬性:android:animateLayoutChanges=“true”,所有派生自ViewGroup的控制元件都具有此屬性,只要在XML中新增上這個屬性,就能實現新增/刪除其中控制元件時,帶有預設動畫了。但是這個屬性設定後,只能使用預設的動畫,不支援自定義動畫。同時在API 11時引入的LayoutTransaction也能起到LayoutAnimation+animateLayoutChanges效果,並且能夠設定自定義動畫。它的使用涉及到屬性動畫,相對LayoutAnimation的使用更復雜,以後再提。
-
通過補間動畫(Tween animation)為Activity自定義切換動畫
Android系統為Activity設定了預設的切換動畫,這個動畫我們是可以進行自定義的。通過呼叫Activity類的overridePendingTransition(int enterAnim, int exitAnim)方法可以實現自定義Activity的切換動畫,注意這個方法必須在startActivity和finish呼叫之後被呼叫,否者沒有效果。
View動畫的缺點
它只是改變了檢視的顯示,但沒有改變檢視的響應區域。也就是說,比如你用ScaleAnimation將檢視放大或縮小,其實檢視的點選響應區域還是動畫開始前的位置;或者用TranslateAnimation將檢視平移到另一個位置,點選響應區域還是在動畫開始前的位置,而動畫結束時檢視所在的區域沒有點選響應。
幀動畫
幀動畫也就是Drawable動畫,是用來逐幀顯示定義好的一組圖片或者Drawable資源。效果類似於範燈片,一張張地切換圖片。對應於AnimationDrawable類。實際的開發中,幀動畫使用的場景相對較少。
典型的用法如下:
首先在res/drawable目錄下通過xml定義一個幀動畫(AnimationDrawable)
<?xml version="1.0" encoding="utf-8"?> <animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="true" > <item android:drawable="@drawable/first_pic" android:duration="1000"/> <item android:drawable="@drawable/second_pic" android:duration="1000"/> <item android:drawable="@drawable/third_pic" android:duration="1000"/> <item android:drawable="@drawable/fourth_pic" android:duration="1000"/> <item android:drawable="@drawable/fifth_pic" android:duration="1000"/> <item android:drawable="@drawable/sixth_pic" android:duration="1000"/> </animation-list>
<animation-list>標籤表示一組幀動畫,oneshot屬性為true,表示動畫只播放一次,否則就會重複播放。每一個item對應每一幀的圖片。duration屬性表示每一幀顯示的時間。
接下來將定義好的AnimationDrawable設定為View的背景或者ImageView的影象
AnimationDrawable animationDrawable = (AnimationDrawable) getResources().getDrawable(R.drawable.anim_list); image.setImageDrawable(animationDrawable); animationDrawable.start();
以上是通過xml的方式定義幀動畫(AnimationDrawable),當然也可以通過程式碼來定義
AnimationDrawable animationDrawable = new AnimationDrawable(); animationDrawable.addFrame(getResources().getDrawable(R.drawable.first_pic), 1000); animationDrawable.addFrame(getResources().getDrawable(R.drawable.second_pic), 1000); animationDrawable.addFrame(getResources().getDrawable(R.drawable.third_pic), 1000); animationDrawable.addFrame(getResources().getDrawable(R.drawable.fourth_pic), 1000); animationDrawable.addFrame(getResources().getDrawable(R.drawable.fifth_pic), 1000); animationDrawable.addFrame(getResources().getDrawable(R.drawable.sixth_pic), 1000); animationDrawable.setOneShot(true); image.setImageDrawable(animationDrawable); animationDrawable.start();
有一點需要強調的是:啟動animationDrawable.start()不能在Activity的onCreate和onStart中呼叫,因為在onCreate和onStart中AnimationDrawable還沒有完全的與ImageView繫結,在onCreate和onStart中啟動動畫,就只能看到第一張圖片。解決的辦法是確保Activity在Resume狀態下呼叫animationDrawable.start()。
幀動畫的缺陷是不能新增監聽事件。