本文是對Android動畫的彙總。關於Android的動畫包括 3.0之前的View Animation,3.0之後的 Property Animator 以及5.0新增的(Touch feedback(觸摸反饋)Reveal effect(揭露效果)Activity transitions(Activity轉換效果)Curved motion(曲線運動)View state changes (視圖狀態改變)Animate Vector Drawables(可繪矢量動畫))6種動畫。
幾種動畫的詳細內容如下:
1. View Animation :
第一類是Tween動畫,就是對場景裏的對象不斷的進行圖像變化來產生動畫效果。
第二類就是 Frame動畫,即順序的播放事先做好的圖像,與gif圖片原理類似。
下面就講一下Tweene Animations。
主要類:
Animation 動畫
AlphaAnimation 漸變透明度
otateAnimation 畫面旋轉
ScaleAnimation 漸變尺寸縮放
ranslateAnimation 位置移動
AnimationSet 動畫集
以自定義View爲例,該View很簡單,畫面上只有一個圖片。 現在我們要對整個View分別實現各種Tween動畫效果。
1) AlphaAnimation實現代碼:
//初始化 Animation alphaAnimation = new AlphaAnimation(0.1f, 1.0f); //設置動畫時間 alphaAnimation.setDuration(3000); this.startAnimation(alphaAnimation);
其中AlphaAnimation類第一個參數fromAlpha表示動畫起始時的透明度, 第二個參數toAlpha表示動畫結束時的透明度。setDuration用來設置動畫持續時間。
fromAlpha、toAlpha屬性說明:0.0表示完全透明 1.0表示完全不透明 以上值取0.0-1.0之間的float數據類型的數字
2) RotateAnimation實現代碼:
Animation rotateAnimation = new RotateAnimation(0f, 360f); rotateAnimation.setDuration(1000); this.startAnimation(rotateAnimation);
其中RotateAnimation類第一個參數fromDegrees表示動畫起始時的角度, 第二個參數toDegrees表示動畫結束時的角度。另外還可以設置伸縮模式pivotXType、pivotYType, 伸縮動畫相對於x,y 座標的開始位置pivotXValue、pivotYValue等 fromDegrees、toDegrees屬性值說明:0.0表示收縮到沒有 1.0表示正常無伸縮 值小於1.0表示收縮 值大於1.0表示放大。
當角度爲負數——表示逆時針旋轉
當角度爲正數——表示順時針旋轉
(負數from——to正數:順時針旋轉)
(負數from——to負數:逆時針旋轉)
(正數from——to正數:順時針旋轉)
(正數from——to負數:逆時針旋轉)
pivotX、pivotY屬性值說明:從0%-100%中取值,50%爲物件的X或Y方向座標上的中點位置
3) ScaleAnimation實現代碼:
//初始化 Animation scaleAnimation = new ScaleAnimation(0.1f, 1.0f,0.1f,1.0f); //設置動畫時間 scaleAnimation.setDuration(500); this.startAnimation(scaleAnimation);
ScaleAnimation類中
第一個參數fromX ,第二個參數toX:分別是動畫起始、結束時X座標上的伸縮尺寸。
第三個參數fromY ,第四個參數toY:分別是動畫起始、結束時Y座標上的伸縮尺寸。
另外還可以設置伸縮模式pivotXType、pivotYType, 伸縮動畫相對於x,y 座標的開始位置pivotXValue、pivotYValue等。
4)TranslateAnimation實現代碼:
//初始化 nimation translateAnimation = new TranslateAnimation(0.1f, 100.0f,0.1f,100.0f); //設置動畫時間 translateAnimation.setDuration(1000); this.startAnimation(translateAnimation);
TranslateAnimation類
第一個參數fromXDelta ,第二個參數toXDelta:分別是動畫起始、結束時X座標。
第三個參數fromYDelta ,第四個參數toYDelta:分別是動畫起始、結束時Y座標。
5)AnimationSet實現代碼:
//初始化 Translate動畫 translateAnimation = new TranslateAnimation(0.1f, 100.0f,0.1f,100.0f); //初始化 Alpha動畫 alphaAnimation = new AlphaAnimation(0.1f, 1.0f); //動畫集 AnimationSet set = new AnimationSet(true); set.addAnimation(translateAnimation); set.addAnimation(alphaAnimation); //設置動畫時間 (作用到每個動畫) set.setDuration(1000); this.startAnimation(set);
6)Interpolator
用於修改一個動畫過程中的速率,可以定義各種各樣的非線性變化函數,比如加速、減速等。
在Android中所有的插值器都是Interpolator 的子類,通過 android:interpolator 屬性你可以引用不同的插值器。下面是幾種插值
你可以通過下面的方式使用它們:
<set android:interpolator="@android:anim/accelerate_interpolator"> </set>
自定義插值器
如果你對系統提供的插值器不滿意,我們可以創建一個插值器資源修改插值器的屬性,比如修改AnticipateInterpolator的加速速率,調整CycleInterpolator的循環次數等。爲了完成這種需求,我們需要創建XML資源文件,然後將其放於/res/anim下,然後再動畫元素中引用即可。我們先來看一下幾種常見的插值器可調整的屬性:
<?xml version="1.0" encoding="utf-8"?>
<InterpolatorName xmlns:android="http://schemas.android.com/apk/res/android"
android:attribute_name="value"
/>
android:factor 浮點值,加速速率,默認爲1
android:tension 浮點值,起始點後退的張力、拉力數,默認爲2
android:tension 同上 android:extraTension 浮點值,拉力的倍數,默認爲1.5(2 * 1.5)
android:cycles int,循環的個數,默認爲1
android:factor 浮點值,減速的速率,默認爲1
浮點值,超出終點後的張力、拉力,默認爲2
比如:res/anim/my_overshoot_interpolator.xml:
<?xml version="1.0" encoding="utf-8"?>
<overshootInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
android:tension="7.0"/>
This animation XML will apply the interpolator:
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@anim/my_overshoot_interpolator"
android:fromXScale="1.0"
android:toXScale="3.0"
android:fromYScale="1.0"
android:toYScale="3.0
android:pivotX="50%"
android:pivotY="50%"
android:duration="700" />
如果簡單的修改插值器的屬性值還不能夠滿足我們的需求,那麼就自己來通過實現Interpolator接口來定義自己的插值器了因爲上面所有的Interpolator都實現了Interpolator接口,這個接口定義了一個方法:float getInterpolation(float input);此方法由系統調用,input代表動畫的時間,在0和1之間,也就是開始和結束之間。
線性(勻速)插值器定義如下:
public float getInterpolation(float input) { return input; }
加速減速插值器定義如下:
public float getInterpolation(float input) { return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f; }
2.PropertyAnimator動畫
Property Animation動畫有兩個步聚:
a.計算屬性值
b.爲目標對象的屬性設置屬性值,即應用和刷新動畫
1) 計算屬性值
過程一:計算已完成動畫分數 elapsed fraction
爲了執行一個動畫,你需要創建一個ValueAnimator,並且指定目標對象屬性的開始、結束值和持續時間。在調用start後的整個動畫過程中, ValueAnimator會根據已經完成的動畫時間計算得到一個0到1之間的分數,代表該動畫的已完成動畫百分比。0表示0%,1表示100%。
過程二:計算插值(動畫變化率)interpolated fraction
當ValueAnimator計算完已完成動畫分數後,它會調用當前設置的TimeInterpolator,去計算得到一個interpolated(插值)分數,在計算過程中,已完成動畫百分比會被加入到新的插值計算中。
過程三:計算屬性值
當插值分數計算完成後,ValueAnimator 會根據插值分數調用合適的 TypeEvaluator去計算運動中的屬性值。
以上分析引入了兩個概念:已完成動畫分數(elapsed fraction)、插值分數( interpolated fraction )。
核心類:
a. Evaluators
Evaluators 告訴屬性動畫系統如何去計算一個屬性值。它們通過Animator提供的動畫的起始和結束值去計算一個動畫的屬性值。
屬性系統提供了以下幾種Evaluators:
1.IntEvaluator
2.FloatEvaluator
3.ArgbEvaluator
這三個由系統提供,分別用於計算int,float,color型(十六進制)屬性的計算器
b.TypeEvaluator
一個用於用戶自定義計算器的接口,如果你的對象屬性值類型,不是int,float,或者color類型,你必須實現這個接口,去定義自己的數據類型。TypeEvaluator接口只有一個方法,就是evaluate()方法,它允許你使用的animator返回一個當前動畫點的屬性值。
c.ValueAnimator
屬性動畫中的主要的時序引擎,如動畫時間,開始、結束屬性值,相應時間屬性值計算方法等。包含了所有計算動畫值的核心函數。也包含了每一個動畫時間上的細節,信息,一個動畫是否重複,是否監聽更新事件等,並且還可以設置自定義的計算類型。
使用ValueAnimator實現動畫需要手動更新:
ValueAnimator animation = ValueAnimator.ofFloat(0f, 1f); animation.setDuration(1000); animation.addUpdateListener(new AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { Log.i("update", ((Float) animation.getAnimatedValue()).toString()); } }); animation.setInterpolator(new CycleInterpolator(3)); animation.start();
d.ObjectAnimator
繼承自ValueAnimator,允許你指定要進行動畫的對象以及該對象的一個屬性。該類會根據計算得到的新值自動更新屬性。ObjectAnimator的自動更新功能,依賴於屬性身上的setter和getter方法,所以爲了讓ObjectAnimator能夠正確的更新屬性值,你必須遵從以下規範:
1. 該對象的屬性必須有get和set方法(方法的格式必須是駝峯式),方法格式爲set(),因爲ObjectAnimator會自動更新屬性,它必須能夠訪問到屬性的setter方法,比如屬性名爲foo,你就需要一個setFoo()方法,如果setter方法不存在,你有三種選擇:
a.添加setter方法
b.使用包裝類。通過該包裝類通過一個有效的setter方法獲取或者改變屬性值的方法,然後應用於原始對象,比如NOA的AnimatorProxy。
c.使用ValueAnimator代替
(這3點的意思總結起來就是一定要有一個setter方法,讓ObjectAnimator能夠訪問到)
如果你爲ObjectAnimator的工廠方法的可變參數只傳遞了一個值,那麼會被作爲動畫的結束值。
e. AnimatorSet
提供組合動畫能力的類。並可設置組中動畫的時序關係,如同時播放、有序播放或延遲播放。Elevator會告訴屬性動畫系統如何計算一個屬性的值,它們會從Animator類中獲取時序數據,比如開始和結束值,並依據這些數據計算動畫的屬性值。
f.ViewPropertyAnimator
可以方便的爲某個View的多個屬性添加並行的動畫,只使用一個ViewPropertyAnimator對象就可以完成。它的行爲更像一個ObjectAnimator,因爲它修改的是對象的實際屬性值。但它爲一次性給多個屬性添加動畫提供了方便,而且使用ViewPropertyAnimator的代碼更連貫更易讀。
下面的代碼段分別展示了使用多個ObjectAnimator對象、一個ObjectAnimator對象、 ViewPropertyAnimator同時爲一個View的X和Y屬性添加動畫的示例:
多個ObjectAnimator結合AnimatorSet實現
ObjectAnimator animX = ObjectAnimator.ofFloat(myView, "x", 50f); ObjectAnimator animY = ObjectAnimator.ofFloat(myView, "y", 100f); AnimatorSet animSetXY = new AnimatorSet(); animSetXY.playTogether(animX, animY); animSetXY.start();
一個ObjectAnimator結合多個PropertyValuesHolder實現
ropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("x", 50f); PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 100f); ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvyY).start();
ViewPropertyAnimator: 只需一行代碼
myView.animate().x(50f).y(100f);//myView.animate()直接返回一個ViewPropertyAnimator對象
g.PropertyValuesHolder
顧名思義,該類持有屬性,相關屬性值的操作以及屬性的setter,getter方法的創建,屬性值以Keyframe來承載,最終由KeyframeSet統一處理。
h.KeyFrame
一個keyframe對象由一對 time / value的鍵值對組成,可以爲動畫定義某一特定時間的特定狀態。每個keyframe可以擁有自己的插值器,用於控制前一幀和當前幀的時間間隔間內的動畫。
Keyframe.ofFloat(0f,0f);
第一個參數爲:要執行該幀動畫的時間節點(elapsed time / duration)
第二個參數爲屬性值。
因此如果你想指定某一特定時間的特定狀態,那麼簡單的使用ObjectAnimator就滿足不了你了,因爲ObjectAnimator.ofInt(....)類似的工廠方法,無法指定特定的時間點的狀態。
每個KeyFrame其實也有個Interpolator。如果沒有設置,默認是線性的。之前爲Animator設置的Interpolator是整個動畫的,而系統允許你爲每一KeyFrame的單獨定義Interpolator,系統這樣做的目的是允許你在某一個keyFrame做特殊的處理,也就是整體上是按照你的插值函數來計算,但是,如果你希望某個或某些KeyFrame會有不同的動畫表現,那麼你可以爲這個keyFrame設置Interpolator。因此,Keyframe的定製性更高,你如果想精確控制某一個時間點的動畫值及其運動規律,你可以自己創建特定的Keyframe 。
Keyframe使用
爲了實例化一個keyframe對象,你必須使用某一個工廠方法:ofInt(), ofFloat(), or ofObject() 去獲取合適的keyframe類型,然後你調用ofKeyframe工廠方法去獲取一個PropertyValuesHolder對象,一旦你擁有了該對象,你可以將PropertyValuesHolder作爲參數獲取一個Animator,如下:
Keyframe kf0 = Keyframe.ofFloat(0f, 0f); Keyframe kf1 = Keyframe.ofFloat(.5f, 360f); Keyframe kf2 = Keyframe.ofFloat(1f, 0f); PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2);//動畫屬性名,可變參數 ObjectAnimator rotationAnim = ObjectAnimator.ofPropertyValuesHolder(target, pvhRotation) rotationAnim.setDuration(5000);
i. KeyFrameSet
根據Animator傳入的值,爲當前動畫創建一個特定類型的KeyFrame集合。
通常通過ObjectAnimator.ofFloat(…)進行賦值時,這些值其實是通過一個KeyFrameSet來維護的
比如:
ObjectAnimator.ofFloat(target, "translateX", 50, 100, 200);
調用者傳入的values 爲 50,100,200,則numKeyframs = 3,那麼創建出相應的Keyframe爲:
Keyframe(0,50),Keyframe(1/2,100),Keyframe(1,200), 時間點 0,1/2,1 都是按比例劃分的
public static KeyframeSet ofFloat(float... values) { int numKeyframes = values.length; FloatKeyframe keyframes[] = new FloatKeyframe[Math.max(numKeyframes,2)]; if (numKeyframes == 1) { keyframes[0] = (FloatKeyframe) Keyframe.ofFloat(0f); keyframes[1] = (FloatKeyframe) Keyframe.ofFloat(1f, values[0]); } else { keyframes[0] = (FloatKeyframe) Keyframe.ofFloat(0f, values[0]); for (int i = 1; i < numKeyframes; ++i) { keyframes[i] = (FloatKeyframe) Keyframe.ofFloat((float) i / (numKeyframes - 1), values[i]);//這裏是關鍵 } } return new FloatKeyframeSet(keyframes);
2) 在XML中聲明屬性動畫
通過在XML中定義的動畫,可以很方便的在多個Activities中重用而且更容易編輯,複用性強。爲了區分新的屬性動畫,從3.1開始,你應res/animator/下存放屬性動畫的資源文件,使用animator文件夾是可選的,但是如果你想在Eclipse ADT插件中使用佈局編輯工具(ADT 11.0.0+),就必須在res/animator文件夾下存放了,因爲ADT只會查找res/animator文件夾下的屬性動畫資源文件。
屬性動畫支持的Tag有
ValueAnimator - <animator>
ObjectAnimator - <objectAnimator>
AnimatorSet - <set>
<set android:ordering="sequentially"> <set> <objectAnimator android:propertyName="x" android:duration="500" android:valueTo="400" android:valueType="intType"/> <objectAnimator android:propertyName="y" android:duration="500" android:valueTo="300" android:valueType="intType"/> </set> <objectAnimator android:propertyName="alpha" android:duration="500" android:valueTo="1f"/> </set>
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext, R.anim.property_animator); set.setTarget(myObject); set.start();
目錄res/animator/filename.xm
編譯後的資源爲ValueAnimator, ObjectAnimator, or AnimatorSet
XML文件的根元素必須爲<set>,<objectAnimator>, or <valueAnimator>之一。也可以在一個set中組織不同的動畫,包含其它<set>元素,也就是說,可以嵌套。
<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>
3.Andriod L的動畫
Material Design是Google推出的一個全新的設計語言,它的特點就是擬物扁平化。
在Android L中新增瞭如下幾種動畫:
a. Touch feedback(觸摸反饋)
b. Reveal effect(揭露效果)
c. Activity transitions(Activity轉換效果)
d. Curved motion(曲線運動)
e. View state changes (視圖狀態改變)
f. Animate Vector Drawables(可繪矢量動畫)
詳細的內容如下:
1. 觸摸反饋:
觸摸反饋最具代表性的就是波紋動畫,比如當點擊按鈕時會從點擊的位置產生類似於波紋的擴散效果。
1)波紋效果(Ripple):
可以通過如下代碼設置波紋的背景:android:background="?android:attr/selectableItemBackground"波紋有邊界 android:background="?android:attr/selectableItemBackgroundBorderless"波紋超出邊界
具體代碼如下:
<Button android:id="@+id/btn_1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/btn_1" android:padding="10px" android:layout_below="@id/touch_feedback_ripple_textview" /> <Button android:id="@+id/btn_2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/btn_2" android:layout_below="@id/btn_1" android:padding="10px" android:background="?android:attr/selectableItemBackground"/> <Button android:id="@+id/btn_3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/btn_3" android:layout_below="@id/btn_2" android:padding="10px" android:background="?android:attr/selectableItemBackgroundBorderless"/>
效果如下:
2)設置顏色
我們也可以通過設置xml屬性來調節動畫顏色,從而可以適應不同的主題:
android:colorControlHighlight:設置波紋顏色
android:colorAccent:設置checkbox等控件的選中顏色
2. Circular Reveal:
使用方法:
應用ViewAnimationUtils.createCircularReveal()方法可以去創建一個RevealAnimator動畫 。
ViewAnimationUtils.createCircularReveal源碼如下:
public static Animator createCircularReveal(View view,nt centerX, int centerY, float startRadius, float endRadius) { return new RevealAnimator(view, centerX, centerY, startRadius, endRadius); }
源碼非常簡單,就是通過createCircularReveal方法根據5個參數來創建一個RevealAnimator動畫對象。
這五個參數分別是:
view 操作的視圖
centerX 動畫開始的中心點X
centerY 動畫開始的中心點Y
startRadius 動畫開始半徑
startRadius 動畫結束半徑
實例代碼:
final View oval = this.findViewById(R.id.oval); oval.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Animator animator = ViewAnimationUtils.createCircularReveal( oval,oval.getWidth()/2,oval.getHeight()/2,oval.getWidth(),0); animator.setInterpolator(new AccelerateDecelerateInterpolator()); animator.setDuration(2000); animator.start(); } }); final View rect = this.findViewById(R.id.rect); rect.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Animator animator = ViewAnimationUtils.createCircularReveal( rect,0,0,0,(float) Math.hypot(rect.getWidth(), rect.getHeight())); animator.setInterpolator(new AccelerateInterpolator()); animator.setDuration(2000); animator.start(); } });
顯示效果:
3. Activity Transition
1) 什麼是Transition?
安卓5.0中Activity和Fragment 變換是建立在名叫Transitions的安卓新特性之上的。這個誕生於4.4的transition框架爲在不同的UI狀態之間產生動畫效果提供了非常方便的API。該框架主要基於兩個概念:場景(scenes)和變換(transitions)。場景(scenes)定義了當前的UI狀態,變換(transitions)則定義了在不同場景之間動畫變化的過程。雖然transition翻譯爲變換似乎很確切,但是總覺得還是沒有直接使用transition直觀,爲了更好的理解下面個別地方直接用transition代表變換。
當一個場景改變的時候,transition主要負責:
(1)捕捉每個View在開始場景和結束場景時的狀態。
(2)根據兩個場景(開始和結束)之間的區別創建一個Animator。
2) Android 5.0(API 級別 21)支持這些進入與退出轉換:
(1)分解 - 從場景中心移入或移出視圖。
(2)滑動 - 從場景邊緣移入或移出視圖。
(3)淡入淡出 - 通過調整透明度在場景中增添或移除視圖。
3)Android 5.0(API 級別 21)也支持這些共享元素轉換:
(1)changeBounds - 爲目標視圖的佈局邊界的變化添加動畫。
(2) changeClipBounds - 爲目標視圖的裁剪邊界的變化添加動畫。
(3)changeTransform - 爲目標視圖的縮放與旋轉變化添加動畫。
(4)changeImageTransform - 爲目標圖像的大小與縮放變化添加動畫。
4) 實現方式:
(1). xml 實現方式:
res/transition/activity_fade.xml
<?xml version="1.0" encoding="utf-8"?> <fade xmlns:android="http://schemas.android.com/apk/res/" android:duration="1000"/> res/transition/activity_slide.xml <?xml version="1.0" encoding="utf-8"?> <slide xmlns:android="http://schemas.android.com/apk/res/" android:duration="1000"/>
MainActivity.java
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_transition); setupWindowAnimations(); } private void setupWindowAnimations() { Slide slide = TransitionInflater.from(this).inflateTransition(R.transition.activity_slide); getWindow().setExitTransition(slide); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_transition); setupWindowAnimations(); } private void setupWindowAnimations() { Fade fade = TransitionInflater.from(this).inflateTransition(R.transition.activity_fade); getWindow().setEnterTransition(fade); }
(2)代碼實現方式:
MainActivity.java
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_transition); setupWindowAnimations(); } private void setupWindowAnimations() { Slide slide = new Slide(); slide.setDuration(1000); getWindow().setExitTransition(slide); }
TransitionActivity.java
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_transition); setupWindowAnimations(); } private void setupWindowAnimations() { Fade fade = new Fade(); fade.setDuration(1000); getWindow().setEnterTransition(fade); }
實例代碼:
(1). Styles文件 :
<resources> <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> <!--設置選中的顏色--> <!-- 允許使用transitions --> <item name="android:windowContentTransitions">true</item> <!--是否覆蓋執行,其實可以理解成是否同步執行還是順序執行--> <item name="android:windowAllowEnterTransitionOverlap">false</item> <item name="android:windowAllowReturnTransitionOverlap">false</item> </style> </resources>
(2). MainActivity部分代碼:
@Override public void onClick(View v) { ArrayList<Pair<View,String>> arrayList = new ArrayList<Pair<View,String>>(); switch (v.getId()) { case R.id.explode_btn: setExplodeTransition(); flag = AnimConstant.EXPLODE_FLAG; break; case R.id.slide_btn: setSlideTransition(); flag = AnimConstant.SLIDE_FLAG; break; case R.id.pade_in_out_btn: setFadeTransition(); flag = AnimConstant.PADE_IN_OUT_FLAG; break; case R.id.shared_element_btn: arrayList.add(new Pair<View, String>(shareElementBtn, "shared_name_btn")); flag = AnimConstant.SHARED_ELEMENTS_FLAG; break; } startActivity(arrayList); } private void setFadeTransition() { Fade fadeTransition = new Fade(); fadeTransition.setDuration(1000); getWindow().setReenterTransition(fadeTransition); getWindow().setExitTransition(fadeTransition); } private void startActivity(ArrayList<Pair<View, String>> arrayList) { Intent intent = new Intent(); intent.setClass(this ,SecondActivity.class); intent.putExtra("transition_flag",flag); ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(this, arrayList.toArray(new Pair[arrayList.size()])); startActivity(intent, options.toBundle()); } private void setExplodeTransition() { Explode explode = new Explode(); explode.setDuration(2000); getWindow().setReenterTransition(explode); getWindow().setExitTransition(explode); } private void setSlideTransition() { Slide slideTransition = new Slide(); slideTransition.setSlideEdge(Gravity.LEFT); slideTransition.setDuration(1000); getWindow().setReenterTransition(slideTransition); getWindow().setExitTransition(slideTransition); }
(3) SecondActivity類:
private Button returnBtn = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_second); Intent intent = getIntent(); int flag = intent.getIntExtra("transition_flag" ,-1); if (flag != AnimConstant.SHARED_ELEMENTS_FLAG) { setupWindowAnimations(); } returnBtn = (Button) this.findViewById(R.id.return_btn); returnBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { finishAfterTransition(); } }); } private void setupWindowAnimations() { Explode explode = new Explode(); explode.setDuration(2000); getWindow().setEnterTransition(explode); }
顯示效果:
4.Curved motion
Material design中的動畫利用曲線實現時間內插與空間移動模式。 在 Android 5.0(API 級別 21)及更高版本,您可爲動畫定義定製時間曲線以及曲線運動模式。PathInterpolator 類別是一個基於貝塞爾曲線或 Path 對象的全新插入器。 此插入器在一個 1x1 的正方形內指定一個運動曲線,定位點位於 (0,0) 以及 (1,1),而控制點則使用構造函數參數指定。
有兩種定義PathInterpolator的方法:
第一種XML方式:
<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" android:controlX1="0.4" android:controlY1="0" android:controlX2="1" android:controlY2="1"/>
系統將爲材料設計規範中的三種基本曲線提供 XML 資源:
@interpolator/fast_out_linear_in.xml
@interpolator/fast_out_slow_in.xml
@interpolator/linear_out_slow_in.xml
第二種代碼實現:
public class SCPahtInterpolator extends PathInterpolator { public static final float DEFALUT_CONTROL_1_X = 0.5f; public static final float DEFALUT_CONTROL_1_Y = 0f; public static final float DEFALUT_CONTROL_2_X = 0f; public static final float DEFALUT_CONTROL_2_Y = 1f; public SCPahtInterpolator() { super(DEFALUT_CONTROL_1_X, DEFALUT_CONTROL_1_Y, DEFALUT_CONTROL_2_X, DEFALUT_CONTROL_2_Y); } public SCPahtInterpolator(Path path) { super(path); } public SCPahtInterpolator(float controlX, float controlY) { super(controlX, controlY); } public SCPahtInterpolator(float controlX1, float controlY1, float controlX2, float controlY2) { super(controlX1, controlY1, controlX2, controlY2); } public SCPahtInterpolator(Context context, AttributeSet attrs) { super(context, attrs); } }
可用Animator.setInterpolator()設置PathInterpolator
ObjectAnimator 類別擁有新的構造函數,可讓您一次使用兩個或更多屬性在路徑上爲座標添加動畫。 例如,下列動畫使用 Path 對象爲視圖的 X 和 Y 屬性添加動畫:
ObjectAnimator mAnimator; mAnimator = ObjectAnimator.ofFloat(view, View.X, View.Y, path); ... mAnimator.start();
5.視圖狀態改變
StateListAnimator 類別讓您能夠定義視圖狀態改變時運行的動畫。 下列示例顯示如何將 StateListAnimator 定義爲一個 XML 資源:
<!-- animate the translationZ property of a view when pressed --> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true"> <set> <objectAnimator android:propertyName="translationZ" android:duration="@android:integer/config_shortAnimTime" android:valueTo="2dp" android:valueType="floatType"/> <!-- you could have other objectAnimator elements here for "x" and "y", or other properties --> </set> </item> <item android:state_enabled="true" android:state_pressed="false" android:state_focused="true"> <set> <objectAnimator android:propertyName="translationZ" android:duration="100" android:valueTo="0" android:valueType="floatType"/> </set> </item> </selector>
如果要將定製視圖狀態動畫附加至一個視圖,請依照此示例使用 XML 資源文件中的 selector 元素定義一個動畫,並使用 android:stateListAnimator屬性將此動畫分配給您的視圖。 如果要將一個狀態列表動畫分配給您的代碼內的一個視圖,請使用 AnimationInflater.loadStateListAnimator() 方法,並以 View.setStateListAnimator() 方法將動畫分配給您的視圖。
當您的主題擴展材料主題時,在默認情況下按鈕將擁有一個 Z 動畫。如果要避免您的按鈕出現這類行爲,請將 android:stateListAnimator 屬性設置爲@null。
AnimatedStateListDrawable 類別讓您能夠創建圖片,顯示相關視圖之間的狀態變化。 Android 5.0 中的某些系統小組件在默認情況下使用這些動畫。 下列示例顯示如何將 AnimatedStateListDrawable 定義爲一個 XML 資源:
<!-- res/drawable/myanimstatedrawable.xml --> <animated-selector xmlns:android="http://schemas.android.com/apk/res/android"> <!-- provide a different drawable for each state--> <item android:id="@+id/pressed" android:drawable="@drawable/drawableP" android:state_pressed="true"/> <item android:id="@+id/focused" android:drawable="@drawable/drawableF" android:state_focused="true"/> <item android:id="@id/default" android:drawable="@drawable/drawableD"/> <!-- specify a transition --> <transition android:fromId="@+id/default" android:toId="@+id/pressed"> <animation-list> <item android:duration="15" android:drawable="@drawable/dt1"/> <item android:duration="15" android:drawable="@drawable/dt2"/> ... </animation-list> </transition> ... </animated-selector>
6.爲矢量圖片添加動畫
矢量圖片可在不丟失定義的情況下縮放。 AnimatedVectorDrawable 類別可讓您爲矢量圖片的屬性添加動畫。
您通常可以在 3 個 XML 文件中定義添加動畫的矢量圖片:
在 res/drawable/ 中擁有 <vector> 元素的矢量圖片
在 res/drawable/ 中擁有 <animated-vector> 元素且已添加動畫的矢量圖片
在 res/anim/ 中擁有 <objectAnimator> 元素的一個或多個對象動畫
添加動畫的矢量圖片可爲 <group> 以及 <path> 元素的屬性添加動畫。<group> 元素定義路徑集或子組,而 <path> 元素則定義將繪製的路徑。
當您定義一個您想要添加動畫的矢量圖片時,請使用 android:name 屬性給這些羣組和路徑指定一個唯一名稱,以便讓您能夠從您的動畫定義中引用這些羣組或路徑。 例如:
<!-- res/drawable/vectordrawable.xml --> <vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="64dp" android:width="64dp" android:viewportHeight="600" android:viewportWidth="600"> <group android:name="rotationGroup" android:pivotX="300.0" android:pivotY="300.0" android:rotation="45.0" > <path android:name="v" android:fillColor="#000000" android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" /> </group> </vector>
已添加動畫的矢量圖片定義按名稱引用矢量圖片內的羣組和路徑:
<!-- res/drawable/animvectordrawable.xml --> <animated-vector xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/vectordrawable" > <target android:name="rotationGroup" android:animation="@anim/rotation" /> <target android:name="v" android:animation="@anim/path_morph" /> </animated-vector>
動畫定義代表着 ObjectAnimator 或 AnimatorSet 對象。此示例中的第一個動畫將目標羣組旋轉 360 度:
<!-- res/anim/rotation.xml --> <objectAnimator android:duration="6000" android:propertyName="rotation" android:valueFrom="0" android:valueTo="360" />
此示例中的第二個動畫對矢量圖片的路徑進行變形。 兩個路徑均需可兼容變形操作:兩個路徑均需擁有相同數量的指令,而且每個指令均需擁有相同數量的參數。
<!-- res/anim/path_morph.xml --> <set xmlns:android="http://schemas.android.com/apk/res/android"> <objectAnimator android:duration="3000" android:propertyName="pathData" android:valueFrom="M300,70 l 0,-70 70,70 0,0 -70,70z" android:valueTo="M300,70 l 0,-70 70,0 0,140 -70,0 z" android:valueType="pathType" /> </set>
引用的文章:
http://www.open-open.com/lib/view/open1416663769680.html
http://blog.csdn.net/feng88724/article/details/6318430
http://www.lightskystreet.com/2015/05/23/anim_basic_knowledge/