而 Android 5.0 (API level 21) 之後則可以對於以下動畫進行客製化:
Touch feedback
Button 的預設 Touch feedback 是使用 RippleDrawable
若想套用這個動畫效果可以把 xml 裡的 background 屬性設為
?android:attr/selectableItemBackground (View 本身範圍內的波紋)
或 API level 21 的新屬性 ?android:attr/selectableItemBackgroundBorderless (View 本身上面, parent 範圍內的波紋)
或是用 xml 以 ripple 標籤定義 RippleDrawable
ripple 的顏色可以用 android:colorControlHighlight 設定
Circular Reveal
Reveal 動畫可以在顯示或隱藏一組 UI 時為使用者提供視覺延續性
ViewAnimationUtils 只有一個 Public Methods
ViewAnimationUtils.createCircularReveal(View view, int centerX, int centerY, float startRadius, float endRadius)
它可以回傳一個圓形裁剪動畫的 Animator
來看一下範例
// invisible 的 view View myView = findViewById(R.id.my_view); // 取得 view 的中心位置做為 clipping circle 的圓心 int cx = myView.getWidth() / 2; int cy = myView.getHeight() / 2; // 取 view 的長邊尺寸做為 clipping circle 的最終半徑大小 int finalRadius = Math.max(myView.getWidth(), myView.getHeight()); // 呼叫 createCircularReveal (startRadius 是 0) Animator anim = ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0, finalRadius); // 將設為 visible 然後進行動畫 myView.setVisibility(View.VISIBLE); anim.start();
如果是隱藏的話就要改成這樣
Animator anim = ViewAnimationUtils.createCircularReveal(myView, cx, cy, initialRadius, 0); // 在 onAnimationEnd 時把 view 設為 invisible anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); myView.setVisibility(View.INVISIBLE); } }); anim.start();
Activity transitions
Activity 間的轉換
可以自訂 enter 跟 exit 以及 shared elements 的 transitions
Android 5.0 (API level 21) 支援的 enter 跟 exit transitions 有:
explode (中心放大/縮小)
slide (滑入/滑出)
fade (淡入/淡出)
只要是繼承自 Visibility 的 Transition 類別都可以做為 enter 跟 exit 的動畫
支援 shared elements 的 transitions 有:
changeBounds (邊界)
changeClipBounds (邊界裁剪)
changeTransform (scale 跟 rotation)
changeImageTransform (圖像的 size 跟 scale)
<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/slide</item> <item name="android:windowExitTransition">@transition/slide</item> <!-- specify shared element transitions --> <item name="android:windowSharedElementEnterTransition"> @transition/shared_element_transition</item> <item name="android:windowSharedElementExitTransition"> @transition/shared_element_transition</item> </style>
transition 的 xml 範例如下
shared_element_transition.xml
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android" android:transitionOrdering="together"> <changeBounds /> <changeTransform /> <changeImageTransform /> </transitionSet>
transition 如果不用 theme 指定的話
也可以用 code 來設定
但要記得 requestFeature
// inside your activity (if you did not enable transitions in your theme) getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS); getWindow().setEnterTransition(new Explode()); Window.setSharedElementEnterTransition(); Window.setSharedElementExitTransition(); getWindow().setExitTransition(new Explode());另外 Window.setAllowEnterTransitionOverlap(true) 可以讓 enter transition 盡快進行
Activity 切換的範例 code 如下:
getWindow().setExitTransition(new Explode()); Intent intent = new Intent(this, MyOtherActivity.class); startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(this).toBundle());
有 sharedElement 的話請參考這裡:
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this, Pair.create(view1, "agreedName1"), Pair.create(view2, "agreedName2")); // start the new activity startActivity(intent, options.toBundle());
Curved motion
Android 5.0 (API level 21) 之後可自訂動畫的時間曲線及補間曲線
新的 PathInterpolator 類別是基於貝茲區線 (Bézier curve) 的 interpolator 或 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"/> </style>
material design specification 中
系統提供了三種基本曲線的 XML resources:
@interpolator/fast_out_linear_in.xml
@interpolator/fast_out_slow_in.xml
@interpolator/linear_out_slow_in.xml
設定 interpolator 的方法是將 PathInterpolator 物件傳入 Animator.setInterpolator 中
Animator.setInterpolator (TimeInterpolator value)
ObjectAnimator 也提供了一些新的 constructor 讓我們傳入 Path 物件, 例如:
ObjectAnimator mAnimator; mAnimator = ObjectAnimator.ofFloat(view, View.X, View.Y, path); ... mAnimator.start();
View state changes
StateListAnimator 讓我們可以在 view 的 state change 間進行動畫
<!-- 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 透過 android:stateListAnimator 屬性指給 view
在 code 裡則是透過 AnimationInflater.loadStateListAnimator (Context context, int id) 將 xml 的 StateListAnimator 載入進來
再用 View.setStateListAnimator(StateListAnimator stateListAnimator) 設定
由於 material theme 的 button 都有 Z 屬性
android:stateListAnimator 如果傳入 @null 則 Z 屬性不會有效
AnimatedStateListDrawable 類別則是 state 間的 drawable 動畫
有些 Android 5.0 的 widget 也是利用這樣的動畫方式
範例如下:
<!-- 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 檔案中定義 animated vector 有三個要素
1. res/drawable/ 中以 vector 標籤為 root 的 xml 檔
注意它是由裡面的 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>
2. res/drawable/ 中以 animated-vector 標籤為 root 的 xml 檔
把 vector 的 xml 檔設定在 android:drawable 屬性
動畫則由 android:animation 屬性來設定
<!-- 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>
3. res/anim/ 中有一個或數個 objectAnimator 標籤的 xml 檔
用來定義動畫
<!-- 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>
相關資料:
Defining Custom Animations
沒有留言:
張貼留言