標籤:des android style blog http io color ar os
動畫在Material Design設計中給使用者反饋放使用者點擊時,並且在程式使用者介面中提供連貫的視覺。Material主題為按鈕(Button)和activity的轉換提供了一些預設的動畫,在android5.0(api 21)和更高的版本,你可以自訂這些動畫和建立一個新動畫:
- Touch feedback(觸摸反饋)
- Circular Reveal(迴圈揭露效果)
- Activity transitions(Activity轉換效果)
- Curved motion(曲線運動)
- View state changes (檢視狀態改變)
自訂觸摸反饋
觸摸反饋在Material Design中在觸摸點提供了一個即時視覺確認當使用者作用在UI元素。按鈕的預設觸摸反饋動畫是使用了新的RippleDrawable類,它會是波紋效果在不同狀態間變換。
大多數情況下,我們可以使用這個功能通過在xml檔案中定義背景:
?android:attr/selectableItemBackground 有界限的波紋
?android:attr/selectableItemBackgroundBorderless 可以超出視圖地區的波紋
?android:attr/selectableItemBackgroundBorderless 是21新添加的api
另外,還以使用ripple元素定義RippleDrawable作為一個xml資源。
你可以給RippleDrawable對象分配一個顏色。使用主題的android:colorControlHighlight屬性可以改變預設的觸摸反饋顏色。
更多資訊,查看RippleDrawable類的api指南。
使用揭露效果
揭露動畫為使用者提供視覺上的持久性擋顯示或者隱藏一組介面元素。ViewAnimationUtils.createCircularReveal()方法使你可以使用動畫效果來揭露或者隱藏一個視圖。
這樣揭露一個先前隱藏的視圖:
// previously invisible viewView myView = findViewById(R.id.my_view);// get the center for the clipping circleint cx = (myView.getLeft() + myView.getRight()) / 2;int cy = (myView.getTop() + myView.getBottom()) / 2;// get the final radius for the clipping circleint finalRadius = Math.max(myView.getWidth(), myView.getHeight());// create the animator for this view (the start radius is zero)Animator anim = ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0, finalRadius);// make the view visible and start the animationmyView.setVisibility(View.VISIBLE);anim.start();
這樣隱藏一個先前顯示的視圖:
// previously visible viewfinal View myView = findViewById(R.id.my_view);// get the center for the clipping circleint cx = (myView.getLeft() + myView.getRight()) / 2;int cy = (myView.getTop() + myView.getBottom()) / 2;// get the initial radius for the clipping circleint initialRadius = myView.getWidth();// create the animation (the final radius is zero)Animator anim = ViewAnimationUtils.createCircularReveal(myView, cx, cy, initialRadius, 0);// make the view invisible when the animation is doneanim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); myView.setVisibility(View.INVISIBLE); }});// start the animationanim.start(); 自訂activity轉換效果
activity間轉換在Material Design程式中提供不同狀態間的視覺串連通過在公用元素上動作或者轉換。你可以為進入或退出的轉換自訂動畫,共用元素在不同的activity之間的轉換效果。
進入過渡決定activity中的視圖怎樣進入情境。比如在爆裂進入過渡效果中,視圖從螢幕外面飛向螢幕中間進入情境。
退出過渡決定activity中的視圖怎樣退出情境。比如,在爆裂退出過渡效果中,視圖從中間向遠處退出情境。
共用元素過渡決定兩個activity之間共用的視圖怎麼在兩個activity之間過渡。比如,兩個activity有一個相同的圖片,在不同的位置和不同的大小,changeImageTransform(圖片變換變化)讓共用元素平滑的平移和縮放圖片在兩個activity之間。
android 5.0(api 21)提供以下進入和退出效果:
- explode(爆裂) - 從情境中間行動裝置檢視進入或者退出
- slide(滑動) - 視圖從情境的一個邊緣進入或者退出
- fade(淡入淡出) - 從情境添加或者移除一個視圖通過改變他的透明
所有過渡效果都繼承Visibility類,因此支援作為一個進入或者退出過渡效果。
更多細節,看Transition類的api指南。
Android5.0(api 21)也支援共用元素過渡效果:
- changeBounds - 改變目標視圖的布局邊界
- changeClipBounds - 裁剪目標視圖邊界
- changeTransform - 改變目標視圖的縮放比例和旋轉角度
- changeImageTransform - 改變靶心圖表片的大小和縮放比例
當你在程式中開啟activity間的過渡動畫時,預設的淡入與淡出效果會在兩個activity之間啟用。
一個共用元素過渡效果
指定過渡效果
首先,使用在從material theme繼承的樣式中,使用android:windowContentTransitions屬性開啟視窗內內容過渡效果。也可以在樣式定義中第一進入,退出,共用元素的效果:
<style name="BaseAppTheme" parent="android:Theme.Material"> <!-- enable window content transitions --> <item name="android:windowContentTransitions">true</item> <!-- specify enter and exit transitions --> <item name="android:windowEnterTransition">@transition/explode</item> <item name="android:windowExitTransition">@transition/explode</item> <!-- specify shared element transitions --> <item name="android:windowSharedElementEnterTransition"> @transition/change_image_transform</item> <item name="android:windowSharedElementExitTransition"> @transition/change_image_transform</item></style>
樣本中的過渡change_image_transform定義如下:
<!-- res/transition/change_image_transform.xml --><!-- (see also Shared Transitions below) --><transitionSet xmlns:android="http://schemas.android.com/apk/res/android"> <changeImageTransform/></transitionSet>
changeImageTransform元素對應ChangeImageTransform類。更多資訊,查看Transition的api指南。
在代碼中啟用視窗內容過渡效果,使用Window.requestFeature()方法:
// inside your activity (if you did not enable transitions in your theme)getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);// set an exit transitiongetWindow().setExitTransition(new Explode());
在代碼中定義過渡效果,使用下面的方法,並傳一個Transition對象:
- Window.setEnterTransition()
- Window.setExitTransition()
- Window.setSharedElementEnterTransition()
- Window.setSharedElementExitTransition()
setExitTransition()和setSharedElementExitTransition()方法為調用的activity定義退出過渡效果,setEnterTransition()和setSharedElementEnterTransition()方法為調用的activity定義進入過渡效果。
為了達到完整的過渡效果,必須在進入的和退出的兩個activity上都啟用window內容過渡。否則,正調用的activity會開始退出過渡,你就會看到視窗過渡效果(比如縮放,或者淡出)。
更快的開始一個進入過渡,使用Window.setAllowEnterTransitionOverlap()方法在被調用的activity。這讓你有更加激動人心的進入過渡效果。
開啟activity使用過渡
如果你為一個activity開啟過渡並且設定了一個退出過渡效果,過渡效果會在你開啟其他activity的時候啟用,像這樣:
startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(this).toBundle());
如果你給第二個activity設定了進入過渡動畫,過渡也會在第二個activity啟動的時候啟用。當你啟動其他的activity時,如果需要禁用過渡效果,提供一個為null的bundle選項。
開啟一個activity包含一個共用元素
使用一個情境過渡動畫在兩個activity之間包括一個共用元素:
- 在theme中開啟視窗內容過渡效果
- 在style中指定一個共用元素過渡效果
- 在xml中定義過渡樣式
- 在兩個activity的樣式檔案中給共用元素分配一個相同的名字使用
android:transitionName屬性
- 使用
ActivityOptions.makeSceneTransitionAnimation()方法。
// get the element that receives the click eventfinal View imgContainerView = findViewById(R.id.img_container);// get the common element for the transition in this activityfinal View androidRobotView = findViewById(R.id.image_small);// define a click listenerimgContainerView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(this, Activity2.class); // create the transition animation - the images in the layouts // of both activities are defined with android:transitionName="robot" ActivityOptions options = ActivityOptions .makeSceneTransitionAnimation(this, androidRobotView, "robot"); // start the new activity startActivity(intent, options.toBundle()); }});
對於在代碼中產生的動態共用視圖,使用`View.setTransitionName()方法在兩個activity中給指定相同的名字。
當完成第二個activity的時候,如果需要逆轉該過渡動畫,使用Activity.finishAfterTransition()方法代替Activity.finish()
開啟一個activity包含多個共用元素
使用一個情境過渡動畫在兩個activity之間包括多於一個共用元素,在兩個activity中定義所有的的共用元素使用android:transitionName屬性(或使用View.setTransitionName()方法在所有的activity中),並且建立一個像下面這樣的ActivityOptions對象:
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this, Pair.create(view1, "agreedName1"), Pair.create(view2, "agreedName2"));
使用曲線運動
Material Design中,動畫依賴時間插值和空間移動模式曲線。在android5.0(api 21)和更高版本,你可以為動畫自訂時間曲線和移動曲線。
PathInterpolator類是一個新的基於貝茲路徑或Path對象的插值器。這個插值器在1*1的正方形上定義了曲線運動,以(0,0)和(1,1)點作為錨點,根據夠照參數控制點。你也可以使用xml檔案的定義一個路徑插值器,如:
<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" android:controlX1="0.4" android:controlY1="0" android:controlX2="1" android:controlY2="1"/>
Material Design設計規範中,系統提供了三個基本曲線的xml資源:
- @interpolator/fast_out_linear_in.xml
- @interpolator/fast_out_slow_in.xml
- @interpolator/linear_out_slow_in.xml
我們可以給Animator.setInterpolator()傳一個PathInterpolator對象來設定。
ObjectAnimator類有新的構造方法,你可以一次使用兩個或者屬性使用path獨立於座標動畫。比如,下面的動畫使用一個Path對象去動作一個視圖的x和y屬性:
ObjectAnimator mAnimator;mAnimator = ObjectAnimator.ofFloat(view, View.X, View.Y, path);...mAnimator.start();
檢視狀態改變動畫
StateListAnimator定義動畫當視圖的狀態改變的時候運行,下面的例子是怎麼在xml中定義一個StateListAnimator動畫:
<!-- 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>
給視圖附加自訂的檢視狀態動畫,使用selector元素在xml檔案中定義一個動畫祥例子中這樣,給視圖分配動畫使用android:stateListAnimator屬性。在代碼中使用,使用AnimationInflater.loadStateListAnimator()方法,並且使用View.setStateListAnimator()方法。
當你的主題是繼承的Material主題,按鈕預設有一個Z動畫。如果需要避免這個動畫,設定android:stateListAnimator屬性為@null 即可。
AnimatedStateListDrawable類讓你建立可繪製圖在相關聯的檢視狀態改變。android5.0的一些系統組件預設使用這些動畫。下面的例子是如何在xml檔案中定義一個AnimatedStateListDrawable:
<!-- 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>
可繪向量動畫
可繪製向量圖在展開時不會失真。AnimatedVectorDrawable類讓你可以在可繪製向量圖上面作用動畫。
通常需要在三個xml檔案中定義可動的向量圖:
一個向量圖使用<vector>元素,放在res/drawable/下。
一個可動的向量圖使用<animated-vector>元素,放在res/drawable/下。
一個或更多個動畫對象使用<objectAnimator>元素,放在res/anim/下。
可動向量圖可以使用<group>和<path>元素。<group>元素定義一系列路徑或者子組,<path>元素定義可繪圖的路徑。
當你定義了一個想要作用動畫的向量可繪製圖,使用android:name屬性給每個group和path指定一個唯一的名字,這樣你可以從動畫的定義中找到他們。比如:
<!-- 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>
可動的向量繪製通過剛剛說到定義的名字,來找到這些path和group:
<!-- 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>
更多的資訊,看AnimatedVectorDrawable的api指南。
PS後記
這個系列終於寫完了,說實話基本上大部分都是翻譯的Google的官方文檔。因為時間問題,再加上自己的英語夠爛,最近越來慢。不過,這樣一下來,加上自己的一些代碼練習,對於Material設計算是能夠基本使用了。可惜,大部分的style還都不能向下相容,只好等5了。
網上有一些大神進來已經開源了一些開源組件,大家可以藉此曲線救國,下次有空在專門整理一下。
本文參考: http://developer.android.com/training/material/animations.html
原文地址:http://blog.isming.me/2014/11/13/creating-app-with-material-design-five-animations/,轉載請註明出處。
建立Material Design風格的Android應用--使用自訂動畫