上篇文章介紹了應用程序內對用戶操做響應的相關方法位置,簡單的響應邏輯能夠是從一個界面Activity
跳轉到另外一個界面Activity
,也能夠是某些視圖View
的相對變化。然而不論是啓動一個界面執行新界面Activity
的生命週期方法,仍是視圖的相對變化,都須要一段時間,因此在響應的最終結果完成以前是有一段空白時間的。而在這段或長或短的時間裏,該怎麼給用戶展現界面呢?這就用到Android系統推薦的動畫流程了。html
廣義上說,Android系統在屏幕上繪製展現給用戶的內容發生變化時,均可以使用相關動畫過渡。與用戶操做的響應一致,根據動畫的做用對象不一樣,展現動畫的效果能夠做用於界面Activity
,也能夠做用於視圖View
。大多文章是基於動畫分類的幀動畫、補間動畫介紹,而這裏將按照動畫的做用對象分別展開介紹。android
視圖動畫能夠做用於任何須要展現動畫效果的視圖View
,視圖動畫是Android系統最原生的一種動畫類型,視圖動畫的定義類能夠查看android.view.animation.Animation,其子類即是視圖動畫的效果分類,包括漸變效果AlphaAnimation
、旋轉效果RotateAnimation
、縮放效果ScaleAnimation
、移動效果TranslateAnimation
、和將上述多種效果集合到一塊兒的合集效果AnimationSet
。ide
因爲視圖View
既能夠在佈局文件中靜態聲明,也能夠在代碼中動態註冊聲明,因此相似的,視圖動畫的聲明也能夠分爲在佈局文件中靜態聲明,和在代碼中動態聲明兩種方式。可是視圖動畫的效果啓動使用,須要根據不一樣的用戶響應決定,因此只能在代碼中動態使用。因爲視圖動畫可能包含大量的效果數據,因此通常推薦視圖動畫靜態聲明+動態使用的方式。佈局
動態聲明的視圖動畫效果,只須要在代碼中定義上述五種動畫效果對應的動畫類,並設置相關數據參數便可。其中動畫
漸變效果AlphaAnimation (float fromAlpha, float toAlpha)必需要設置fromAlpha參數做爲漸變效果的起始透明度,toAlpha參數做爲漸變效果的結束透明度。this
旋轉效果RotateAnimation(float fromDegrees, float toDegrees, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)必需要設置fromDegrees參數做爲旋轉效果的起始旋轉角度,和toDegrees參數做爲旋轉效果的結束旋轉角度;其餘參數可選,包括屏幕座標形式的後四個參數,pivotXType參數爲pivotXValue參數類型,pivotXValue參數爲繞x軸旋轉的角度值,同理,pivotYType參數爲pivotYValue參數類型,pivotYValue參數爲繞y軸旋轉的角度值。其中的參數類型包括Animation.ABSOLUTE
絕對類型,其參數值表示絕對數值;Animation.RELATIVE_TO_SELF
相對自身視圖類型,其參數值爲相對自身視圖在動畫效果前的百分值;Animation.RELATIVE_TO_PARENT
相對父視圖類型,其參數值爲相對父視圖在動畫效果前的百分值。google
縮放效果ScaleAnimation(float fromX, float toX, float fromY, float toY, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)也是以屏幕座標的形式記錄參數,必需要設置fromX參數做爲縮放效果開始時在x軸方向的比例,toX參數做爲縮放效果結束時在x軸方向的比例,同理,fromY參數做爲縮放效果開始時在y軸方向的比例,toY參數做爲縮放效果結束時在y軸方向的比例;其餘參數可選,其含義與旋轉效果的可選參數相似。code
移動效果TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta)和TranslateAnimation(int fromXType, float fromXValue, int toXType, float toXValue, int fromYType, float fromYValue, int toYType, float toYValue)一樣是以屏幕座標的形式記錄參數,這兩個構造方法能夠任選一種,其中當八參構造方法中的Type系列參數值爲Animation.RELATIVE_TO_SELF
時,Value系列參數所表示的數據與四參構造方法的Delta系列參數一致。xml
合集效果AnimationSet(boolean shareInterpolator)能夠根據shareInterpolator參數決定該動畫內的一系列動畫展現時是否使用當前類對象中定義的插值器,以後能夠調用該對象的addAnimation(Animation a)
依次放入要執行的系列視圖動畫對象。htm
這裏提到的插值器,是實現了android.view.animation.Interpolator接口的類,這些插值器類計算了視圖動畫效果中從開始到結束之間那段時間的效果展現,在上述視圖動畫效果Animation對象中,能夠經過調用setInterpolator(Interpolator i)
方法設置,若是不設置會默認使用android.view.animation.LinearInterpolator線性插值器。
上述五種效果類的構造方法中,還有一種(Context context, AttributeSet attrs)
參數的構造方法,使用該構造方法能夠經過參數二attrs傳入靜態聲明的動畫資源文件,從而在代碼中使用實例化對象。
靜態聲明的視圖動畫文件,必須保存在res/anim/資源目錄下,符合xml格式的文件。該文件的根標籤必須是五種視圖動畫效果之一,包括漸變效果<alpha></alpha>
、旋轉效果<scale></scale>
、縮放效果<rotate></rotate>
、移動效果<translate></translate>
、合集效果<set></set>
。而其中的必選參數和可選參數也都與代碼動態聲明中的相對應。
最終均可以在代碼中獲得上述五種視圖動畫類的實例化對象。能夠調用setAnimationListener(Animation.AnimationListener listener)
設置動畫執行的監聽,在實現的android.view.animation.Animation.AnimationListener接口實例中,能夠分別實現onAnimationStart(Animation animation)
動畫開始前、onAnimationRepeat(Animation animation)
動畫重複時、onAnimationEnd(Animation animation)
動畫結束時的回調監聽。在啓動動畫展現的地方,調用startNow()
方法能夠當即開始;或者先調用setStartTime(long startTimeMillis)
設置啓動的延時時間,再調用start()
方法開始計時,等延時時間以後開始展現動畫。
在AndroidSDK提供的系統視圖中,有一種相似幕布繪製圖像的系列視圖,像android.widget.ImageView,這種具備繪製像素位圖功能的視圖,更適合在其中繪製展現多張圖片連續組合的幀動畫。本質上圖片動畫只是一系列圖片的組合,因此其聲明和使用方式更隨意,不只能夠在代碼中動態聲明+動態使用的方式,也能夠直接在資源文件中靜態聲明+靜態使用。不過由於圖片動畫須要加載大量的圖片,因此在代碼中動態聲明使用的方式是在應用程序運行過程當中執行的,可能會影響用戶的流暢度,因此推薦圖片動畫使用靜態聲明+靜態使用的方式。
動態聲明的圖片動畫可使用android.graphics.drawable.AnimationDrawable類實例化加載位圖組成的幀動畫。以後依次調用該對象的addFrame(Drawable frame, int duration)
方法增長要展現的每一幀圖片,其中參數一frame
即指定了要加載的圖片資源,參數二duration
則表示當前圖片資源幀在整個動畫播放中的時長,單位是毫米。也能夠調用該對象的setOneShot(boolean oneShot)
設置當前系列幀的圖片動畫是否只播放一遍。最終在須要啓動圖片動畫的位置,調用該對象的start()
,而在須要中止圖片動畫的位置,調用對象的stop()
。
這裏須要注意的是,圖片動畫啓動的
start()
方法必需要在界面Activity
的聲明週期方法執行完onCreate()
以後調用。
靜態聲明的圖片動畫文件,必須保存在res/drawable/目錄下,符合xml格式的文件。該文件的根標籤必須是<animation-list></animation-list>
,在該標籤中可使用android:oneshot
屬性值爲true
或false
,來表示當前系列幀的圖片動畫是否只播放一遍。而其中的每一幀圖片使用<item />
中的android:drawable
屬性值做爲drawable
資源文件引用,同時要經過android:duration
屬性值設置當前圖片幀的展現時長,根據人眼的識別速度,一般設置在1000(單位毫秒)如下。以後若是想靜態使用,能夠在要顯示動畫的視圖中,經過設置其android:backgroud
屬性,並將靜態聲明的資源文件名做爲drawable
資源類型賦值,便可關聯使用。若是想動態使用,首先在代碼中找到要顯示動畫的視圖對應的對象,調用該對象的setBackgroundResource(int res)
,一樣將靜態聲明的資源文件名做爲R.drawable
資源類型賦值,也可關聯使用。最終,在須要啓動圖片動畫的代碼中,經過調用視圖對象的getBackgroud()
方法獲取到圖片動畫的接口android.graphics.drawable.Animatable對象,就能夠在須要啓動和中止圖片動畫的位置分別調用start()
和stop()
方法。
另外, 在Android5.0 即API 21及以上的版本中,經過在項目modle中增長項目依賴庫support-vector-drawable和animated-vector-drawable,以支持在資源文件中定義繪製矢量圖,在AndroidStudio建立默認項目時,所使用的默認應用icon就是矢量圖對象,其優點就是縮放仍不失真、體積小等,這裏不詳介紹。針對這種矢量圖對象,也能夠更加快速的增長矢量圖動畫。因爲矢量圖只能在資源文件中靜態聲明,相應的,矢量圖動畫也只能在資源文件中靜態聲明。這種動畫效果主要依賴於android.graphics.drawable.AnimatedVectorDrawable類或最新包向下兼容的androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat類。
矢量圖的聲明是在res/drawable/
資源目錄下,以<vector></vector>
標籤所包裹的一層表示普通矢量圖,能夠在該標籤內部增長<group></group>
標籤包裹一組動畫效果,設置其android:name
屬性標記該組動畫名稱,同時使用視圖動畫相關屬性值做爲視圖動畫效果展現,包括漸變、旋轉、縮放、平移。也能夠在<group>
標籤內部,繼續使用<path></path>
標籤訂義一系列路徑,一樣須要設置其android:name
屬性標記該組路徑名稱。
矢量動畫的聲明是在res/animator/
資源目錄下,以<objectAnimator></objectAnimator>
爲根標籤包裹的動畫效果,經過設置其android:propertyName
屬性值,能夠描述視圖動畫效果中的漸變、縮放、旋轉、平移等效果,其內部屬性與靜態聲明的視圖動畫中的屬性相似。而以<set></set>
爲根標籤則能夠包裹一系列上述四種動畫效果所表示的<objectAnimator></objectAnimator>
標籤。
最後是將矢量圖與矢量動畫關聯使用,須要在res/drawable
資源目錄下建立新的xml資源文件,以<animated-vector></animated-vector>
做爲根標籤,並設置其android:drawable
屬性並引用上述普通矢量圖資源文件爲drawable
資源類型賦值。在根標籤內經過<target android:name="" android:animation="" />
分別爲矢量圖定義中的android:name
屬性值與矢量圖聲明中的資源文件相關聯。最終在引用普通矢量圖資源文件的位置改成引用動畫矢量圖資源文件。
界面動畫僅在Android5.0即 API 21 及以上的版本中支持。界面動畫做用於界面Activity
,只有在兩個界面Activity
相互啓動切換時,才須要展現界面動畫,所以界面動畫的展現對象主要分三種,包括做爲舊界面Activity
在退出時動畫效果,做爲新界面Activity
在進入動畫效果,和兩個界面之間若是有相同內容的同類視圖,稱之爲共享視圖,其在界面切換時的動畫效果。而關於這些對象的動畫效果,AndroidSDK提供了一些統一的動畫效果可供選擇,包括針對退出和進入動畫的淡入淡出效果的android.transition.Fade類、移動效果android.transition.Slide類、爆炸效果android.transition.Explode類;還有針對共享視圖的視圖動畫效果。或者也能夠繼承android.transition.Transition實現自定義動畫效果。
因爲界面Activity
的定義是在清單文件中靜態註冊的,因此界面動畫的使用也能夠在註冊時採用靜態聲明使用的方式。在靜態使用時用到了<activity android:style/>
樣式屬性,該屬性值是已經定義了<style></style>
標籤的xml格式的樣式資源文件。在<style>
樣式標籤中,必須包含屬性parent="android:Theme.Material"
或其子樣式名。
要想啓動界面動畫,首先在該樣式中增長一條開關控制。
<item name="android:windowActivityTransitions">true</item>
以後重寫該樣式標籤中的<item>
標籤,根據name
屬性值控制不一樣的動畫對象,而根據<item></item>
標籤值指定不一樣的動畫效果。這裏將不一樣動畫對象對應關係列爲下列表格。
動畫對象 | name值 |
---|---|
做爲新界面進入動畫 | android:windowEnterTransition |
做爲舊界面退出動畫 | android:windowExitTransition |
做爲新界面進入時共享視圖動畫 | android:windowSharedElementEnterTransition |
做爲舊界面退出時共享視圖動畫 | android:windowSharedElementExitTransition |
既然界面動畫是經過樣式定義的方式靜態聲明,那確定也能在界面Activity
建立後的方法回調中經過代碼動態聲明使用。這裏用到了android.view.Window類,由於樣式的修改要在界面加載佈局以前,因此在setContentView()
方法以前,經過調用getWindow()
方法能夠獲得Window
對象。
首先一樣須要調用該對象的requestFeature(Window.FEATURE_CONTENT_TRANSITIONS)
方法開啓界面動畫開關。
以後調用該對象的系列方法來控制不一樣動畫對象,根據傳入的Transition
對象的實例指定不一樣的動畫效果。不一樣動畫對象的對應關係以下表。
動畫對象 | Window類調用方法 |
---|---|
做爲新界面進入動畫 | setEnterTransition() |
做爲舊界面退出動畫 | setExitTransition() |
做爲新界面進入時共享視圖動畫 | setSharedElementEnterTransition() |
做爲舊界面退出時共享視圖動畫 | setSharedElementExitTransition() |
針對共享視圖的動畫,還須要分別在兩個佈局文件中標記共享視圖,使用android:transitionName
屬性指定相同的共享視圖名字。
在聲明界面動畫效果後,還須要在該界面做爲新界面被啓動的位置或者該界面做爲舊界面啓動其餘界面的位置,將原有的startActivity(Intent intent)
方法修改成startActivity(Intent intent, Bundle bundle)
方法。其中的intent
參數仍是以前要啓動界面的意圖信息,bundle
參數則是新增的控制界面動畫的數據包。能夠經過ActivityOptions.makeSceneTransitionAnimation(this).toBundle()
系列方法獲取當前界面聲明的界面動畫效果,其結果值做爲android.os.Bundle對象傳入便可。
若是在界面動畫中有單個共享視圖動畫,能夠參考
ActivityOptions.makeSceneTransitionAnimation(Activity activity, View sharedElement, String sharedElementName)
方法。
若是在界面動畫中有多個共享視圖動畫,能夠參考
ActivityOptions.makeSceneTransitionAnimation(Activity activity, Pair...<View, String> sharedElements)
方法。
除了上面做用於三種對象的基本動畫類型,Android系統還提供了一種做用於任何對象的屬性動畫,該動畫具備更全面的功能,詳情可期待下篇文章。