材料設計中的動畫對用戶的操作給予了反饋,並且在與應用交互時提供了持續的可見性。材料主題提供了一些按鈕動畫和活動過渡,Android 5.0允許你自定義動畫並且可以創建新的動畫:
-
Touch Feedback
-
Circular Reveal
-
Activity Transitions
-
Curved Motion
-
View State Changes
自定義觸摸反饋
在用戶與UI元素交互時,從接觸的角度來看,材料設計中的觸摸反饋提供了瞬間的視覺確認。按鈕的默認觸摸動畫使用了新的RippleDrawable
類,使得按鈕采用漣漪效果在不同的狀態之間過渡。
在大多數情況下,你應該像下面那樣在xml
中通過設置視圖背景來應用這個功能:
?android:attr/selectableItemBackground
用於有界漣漪效果。?android:attr/selectableItemBackgroundBorderless
用於拓展到視圖外面的漣漪效果。這個效果將被繪制並局限於此視圖具有非空背景的最近的你控件中。
注意:selectableItemBackgroundBorderless
是API 21中的新屬性。
另外,你也可以通過使用ripple
元素的xml
資源來定義RippleDrawable
。
你可能給RippleDrawable
對象布置顏色。要想改變默認的觸摸反饋顏色,得使用該主題的android:colorControlHighlight
屬性。
使用揭露效果
在你想要顯示或者隱藏一組UI元素時,揭露動畫向用戶提供了持續地可見性。ViewAnimationUtils.createCircularReveal()
方法使你在揭露或隱藏視圖時產生一個裁剪圈似的動畫。
使用如下效果來揭露之前不可見的視圖:

1 // previously invisible view 2 View myView = findViewById(R.id.my_view); 3 // get the center for the clipping circle 4 int cx = (myView.getLeft() + myView.getRight()) / 2; 5 int cy = (myView.getTop() + myView.getBottom()) / 2; 6 // get the final radius for the clipping circle 7 int finalRadius = Math.max(myView.getWidth(), myView.getHeight()); 8 // create the animator for this view (the start radius is zero) 9 Animator anim = ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0, finalRadius); 10 // make the view visible and start the animation 11 myView.setVisibility(View.VISIBLE); 12 anim.start();
使用如下效果來隱藏之前可見的視圖:

1 // previously visible view 2 final View myView = findViewById(R.id.my_view); 3 // get the center for the clipping circle 4 int cx = (myView.getLeft() + myView.getRight()) / 2; 5 int cy = (myView.getTop() + myView.getBottom()) / 2; 6 // get the initial radius for the clipping circle 7 int initialRadius = myView.getWidth(); 8 // create the animation (the final radius is zero) 9 Animator anim = ViewAnimationUtils.createCircularReveal(myView, cx, cy, initialRadius, 0); 10 // make the view invisible when the animation is done 11 anim.addListener(new AnimatorListenerAdapter() { 12 @Override 13 public void onAnimationEnd(Animator animation) { 14 super.onAnimationEnd(animation); 15 myView.setVisibility(View.INVISIBLE); 16 } 17 }); 18 // start the animation 19 anim.start();
自定義Activity
過渡效果
符合材料設計的應用中的Activity
過渡效果,在不同狀態之間,通過常用元素之間的動作和轉換,提供了視覺連接。你可以為Activity
之間出入過渡和共享元素過渡效果指定自定義動畫。
進入過渡效果決定了activity
中的視圖組是如何進入屏幕的。例如,在explode
進入過渡效果中,視圖從外面進入屏幕,並飛入屏幕中心。
退出過渡效果決定了activity
中的視圖組是如何退出屏幕的。例如,在explode
退出過渡效果中,視圖是從中心位置退出屏幕的。
共享元素過渡效果決定了兩個activity
之間共享的視圖在這些activity
之間是如何過渡的。例如,如果兩個activity
擁有不同的位置和尺寸的相同的圖片,共享元素的changeImageTransform
過渡效果將在這些activity
之間順滑地平移和縮放這些圖片。
Android 5.0(API 21)
支持這些出入過渡效果:
explode
—從屏幕中心位置移入移出視圖;slide
—從屏幕地邊緣位置移入移出視圖;fade
—通過改變視圖的透明度從屏幕中添加或刪除視圖;
任何繼承了Visibility
類的過渡效果都可以作為出入過渡效果。
Android 5.0(API 21)
支持這些共享元素過渡效果:
changeBounds
—使目標視圖的布局邊緣變化生成動畫效果;changeClipBounds
—使目標視圖的剪裁邊緣變化生成動畫效果;changeTransform
—使目標視圖的縮放和旋轉變化生成動畫效果;changeImageTransform
—使目標視圖的尺寸和縮放變化生成動畫效果;
當你在應用中使用activity
過渡效果時,在Activity
的進入和退出之間默認的交錯退色效果被激活。
指定自定義過渡效果
首先,在你定義一個繼承自材料主題的風格時,通過android:windowContentTransitions
屬性激活窗口內容過渡效果。你也可以在風格定義中指定出入和共享元素過渡效果:

1 <style name="BaseAppTheme" parent="android:Theme.Material"> 2 <!-- enable window content transitions --> 3 <item name="android:windowContentTransitions">true</item> 4 5 <!-- specify enter and exit transitions --> 6 <item name="android:windowEnterTransition">@transition/explode</item> 7 <item name="android:windowExitTransition">@transition/explode</item> 8 9 <!-- specify shared element transitions --> 10 <item name="android:windowSharedElementEnterTransition"> 11 @transition/change_image_transform</item> 12 <item name="android:windowSharedElementExitTransition"> 13 @transition/change_image_transform</item> 14 </style>
這個例子子中的change_image_transform
過渡效果定義如下:

1 <!-- res/transition/change_image_transform.xml --> 2 <!-- (see also Shared Transitions below) --> 3 <transitionSet xmlns:android="http://schemas.android.com/apk/res/android"> 4 <changeImageTransform/> 5 </transitionSet>
changeImageTransform
元素對應於ChangeImageTransform
類。
要想激活代碼中的窗口內容過渡效果,得調用Window.requestFeature()
方法:

1 // inside your activity (if you did not enable transitions in your theme) 2 getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS); 3 // set an exit transition 4 getWindow().setExitTransition(new Explode());
要在代碼中指定過渡效果,調用這些方法使用Transition
類:
- Window.setEnterTransition();
- Window.setExitTransition();
- Window.setSharedElementEnterTransition();
- Window.setSharedElementExitTransition();
方法setEnterTransition()
和setSharedElementExitTransition()
給調用者Acivity
定義了退出過渡效果,而方法setEnterTransition()
和setSharedElementEnterTransition()
為被調用者定義了進入過渡效果。
為了獲取過渡的全部效果,你必須激活調用和被調用Activity
的窗口內容過渡效果。否則的話,否則的話,調用者Activity
將會啟動退出過渡效果,但是你會看到這個窗口過渡效果的(例如縮放或者褪色)。
為了盡可能早的啟動進入過渡效果,得在被調用Activity
中使用Window.setAllowEnterTransitionOverlap()
。這將使你擁有更多戲劇般美妙的進入過渡效果。
啟動使用過渡效果的Activity
如果你對Activity
啟動並設置了退出過渡效果,過渡效果將如下所示一樣,在你啟動另外一個Activity
時被激活:startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(this).toBundle());
如果你對第二個Activity
設置了進入過渡效果,這個過渡效果將會在該Activity
啟動時被激活。要想在啟動另外一個Activity
時取消過渡效果,你需要提供null
的候選Bundle
。
啟動擁有共享元素的Activity
為了在擁有共享元素的兩個Activity
之間的過渡產生動畫效果:
-
1,主題中支持窗口內容過渡效果。
-
2,風格中指定共享元素過渡效果。
-
3,在xml中定義過渡效果。
-
4,在包含屬性的兩個布局文件中,給共享元素分配相同的名字。
-
5,使用ActivityOptions.makeSceneTransitionAnimation() 方法。

1 // get the element that receives the click event 2 final View imgContainerView = findViewById(R.id.img_container); 3 // get the common element for the transition in this activity 4 final View androidRobotView = findViewById(R.id.image_small); 5 // define a click listener 6 imgContainerView.setOnClickListener(new View.OnClickListener() { 7 @Override 8 public void onClick(View view) { 9 Intent intent = new Intent(this, Activity2.class); 10 // create the transition animation - the images in the layouts 11 // of both activities are defined with android:transitionName="robot" 12 ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this, androidRobotView, "robot"); 13 // start the new activity 14 startActivity(intent, options.toBundle()); 15 } 16 });
對於代碼中生成的動態共享視圖而言,要在兩個Activity
中使用View.setTransitionName()
方法指定共同的元素名字。
為了結束掉第二個Activity
時逆轉屏幕過渡效果動畫,要調用Activity.finishAfterTransition()
方法而非Activity.finish()
。
啟動擁有多個共享元素的Activity
要使擁有多於一個共享元素的兩個Activity
的屏幕過渡產生動畫效果,要在擁有android:transitionName
屬性(或者在兩個Activity
中使用View.setTransitionName()
方法)的兩個布局文件中定義共享元素,並且要按照如下所示創建ActivityOptions
對象:
1 ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this, Pair.create(view1, "agreedName1"), Pair.create(view2, "agreedName2"));
使用弧形運動
材料設計中的動畫依賴於實現了時間加速和空間運動的弧形。Android 5.0(API 21)
以上,你可以給動畫自定義計時弧形和弧形運動模式。
PathInterpolator
類是新的基於貝賽爾曲線或者Path
類的加速器。這個加速器詳細說明了在1x1
方格中的動作曲線,它的錨頭指在(0, 0)
和(1, 1)
之間,並且控制點使用了構造函數中聲明的值。你也可以在xml
文件中定義路徑加速器:

1 <pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" 2 android:controlX1="0.4" 3 android:controlY1="0" 4 android:controlX2="1" 5 android:controlY2="1"/>
系統為材料設計中的三個基礎弧線提供了xml
資源:

1 @interpolator/fast_out_linear_in.xml 2 @interpolator/fast_out_slow_in.xml 3 @interpolator/linear_out_slow_in.xml
你可以把PathInterpolator
對象傳給Animator.setInterpolator()
方法。
ObjectAnimator
對象擁有新的構造器,使得你能夠坐標沿着一個一次使用兩個或者多個屬性的路徑。例如,下面的動畫使用了Path
對象使得視圖的X
和Y
屬性產生動畫效果:

1 ObjectAnimator mAnimator; 2 mAnimator = ObjectAnimator.ofFloat(view, View.X, View.Y, path); 3 ... 4 mAnimator.start();
將視圖的狀態變化產生動畫效果
StateListAnimator
對象讓你定義在視圖狀態變化時運行的動畫。下面的例子向你展示如何將StateListAnimator
定義成xml
資源:

1 <!-- animate the translationZ property of a view when pressed --> 2 <selector xmlns:android="http://schemas.android.com/apk/res/android"> 3 <item android:state_pressed="true"> 4 <set> 5 <objectAnimator android:propertyName="translationZ" 6 android:duration="@android:integer/config_shortAnimTime" 7 android:valueTo="2dp" 8 android:valueType="floatType"/> 9 <!-- you could have other objectAnimator elements 10 here for "x" and "y", or other properties --> 11 </set> 12 </item> 13 <item android:state_enabled="true" 14 android:state_pressed="false" 15 android:state_focused="true"> 16 <set> 17 <objectAnimator android:propertyName="translationZ" 18 android:duration="100" 19 android:valueTo="0" 20 android:valueType="floatType"/> 21 </set> 22 </item> 23 </selector>
要將自定義的視圖狀態動畫添加到視圖上,要像上述例子一樣,將一個動畫使用xml
資源文件中的selector
元素定義出來,而且把它通過android:stateListAnimator
屬性分配到你的視圖上。要在代碼中把狀態列表動畫分配到視圖中,要使用AnimationInflater.loadStateListAnimator()
方法,並且使用View.setStateListAnimator()
方法把動畫分配到你的視圖中。
當你的主題繼承自材料主題時,按鈕在默認情況下有Z
動畫。要在你的按鈕中避免這種行為,需要把android:stateListAnimator
屬性設置成@null
。
AnimatorStateListDrawable
類讓你創建相關聯狀態變化時展示動畫的drawable
。Android 5.0
中的某些系統控件默認使用這些動畫。下面的例子展示了如何使用xml
資源定義AnimatedStateListDrawable
類:

1 <!-- res/drawable/myanimstatedrawable.xml --> 2 <animated-selector 3 xmlns:android="http://schemas.android.com/apk/res/android"> 4 5 <!-- provide a different drawable for each state--> 6 <item android:id="@+id/pressed" android:drawable="@drawable/drawableP" 7 android:state_pressed="true"/> 8 <item android:id="@+id/focused" android:drawable="@drawable/drawableF" 9 android:state_focused="true"/> 10 <item android:id="@id/default" 11 android:drawable="@drawable/drawableD"/> 12 13 <!-- specify a transition --> 14 <transition android:fromId="@+id/default" android:toId="@+id/pressed"> 15 <animation-list> 16 <item android:duration="15" android:drawable="@drawable/dt1"/> 17 <item android:duration="15" android:drawable="@drawable/dt2"/> 18 ... 19 </animation-list> 20 </transition> 21 ... 22 </animated-selector>
使矢量Drawable
產生動畫
矢量圖可縮放但卻不損失精度。AnimatedVectorDrawable
類讓你將矢量圖的屬性產生動畫。
你通常情況下在下面三個xml
文件中定義動畫矢量圖:
- 在res/drawable/目錄下定義擁有元素的矢量圖;
- 在res/drawable/目錄下定義擁有元素的可動畫矢量圖;
- 在res/anim/目錄下定義擁有元素的一個或者多個對象動畫。
可動畫矢量圖能夠將和
等元素的屬性產生動畫。元素定義了一系列的
path
和group
,而
元素定義了要被繪制的path
。
當你定義想要產生動畫的矢量圖時,要使用android:name
屬性對group
和path
分配唯一的名字。由此,你可以用從你的動畫定義中引用它們,例如:

1 !-- res/drawable/vectordrawable.xml --> 2 <vector xmlns:android="http://schemas.android.com/apk/res/android" 3 android:height="64dp" 4 android:width="64dp" 5 android:viewportHeight="600" 6 android:viewportWidth="600"> 7 <group 8 android:name="rotationGroup" 9 android:pivotX="300.0" 10 android:pivotY="300.0" 11 android:rotation="45.0" > 12 <path 13 android:name="v" 14 android:fillColor="#000000" 15 android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" /> 16 </group> 17 </vector>
可動畫矢量圖定義通過他們的名字引用了group
和path
:

1 <!-- res/drawable/animvectordrawable.xml --> 2 <animated-vector xmlns:android="http://schemas.android.com/apk/res/android" 3 android:drawable="@drawable/vectordrawable" > 4 <target 5 android:name="rotationGroup" 6 android:animation="@anim/rotation" /> 7 <target 8 android:name="v" 9 android:animation="@anim/path_morph" /> 10 </animated-vector>
這些動畫定義表示ObjectAnimator
或AnimatorSet
對象。這個例子中的第一個動畫器將目標group
旋轉了360度:

1 <!-- res/anim/rotation.xml --> 2 <objectAnimator 3 android:duration="6000" 4 android:propertyName="rotation" 5 android:valueFrom="0" 6 android:valueTo="360" />
例子中的第二個動畫器使矢量圖的路徑從一種形狀變化為另外一種。兩個路徑必須兼容於產生形變:它們必須擁有相同數量的命令,每個命令必須有相同數量的參數:

1 <!-- res/anim/path_morph.xml --> 2 <set xmlns:android="http://schemas.android.com/apk/res/android"> 3 <objectAnimator 4 android:duration="3000" 5 android:propertyName="pathData" 6 android:valueFrom="M300,70 l 0,-70 70,70 0,0 -70,70z" 7 android:valueTo="M300,70 l 0,-70 70,0 0,140 -70,0 z" 8 android:valueType="pathType" /> 9 </set>