Layout動畫:在android佈局發生變化時新增動畫效果
layout動畫在每次佈局發生變化的時候系統呼叫的一個預載入動畫效果,使用layout動畫可以讓佈局的變化過度看起來更自然。使用起來很簡單,只需在控制元件中新增一個屬性就可以了,系統預設是不會啟動layout動畫的,因此我們平時的應用中不會產生這個效果。
當然,如果你想自定義一下這個動畫效果,那就必須在程式碼中自己寫了:新建一個LayoutTransition物件,呼叫setLayoutTransition()方法來為layout設定動畫。
下面是在xml中通過設定屬性得到的預設動畫效果:
使用方法:
在activity的xml中,設定android:animateLayoutChanges屬性:
<LinearLayout android:id="@+id/container"
android:animateLayoutChanges="true"
...
/>
這樣,當該LinearLayout中的佈局發生變化時,將會有動畫效果。
什麼情況下佈局會在執行時改變呢,一般都是你的程式碼中呼叫了addView 之類的方法:
private ViewGroup mContainerView;
...
private void addItem() {
View newView;
...
mContainerView.addView(newView, 0 );
}
好了,這個東西很簡單,只是平時很少注意到,只要記得android自帶這個功能就行了,免得到時候自己去實現。
Android LayoutAnimation使用及擴充套件
在Android中,最簡單的動畫就是補間動畫了。通過補間動畫,可以對一個控制元件進行位移、縮放、旋轉、改變透明度等動畫。但是補間動畫只能對一個控制元件使用,如果要對某一組控制元件播放一樣的動畫的話,可以考慮layout-animation。
LayoutAnimation
layout-animation可由xml和程式碼兩種方式配置:
XML配置
由於layout-animation是對於某一組控制元件的操作,就需要一個基本的動畫來定義單個控制元件的動畫。另外還可以定義動畫的顯示順序和延遲:
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
android:delay="30%"
android:animationOrder="reverse"
android:animation="@anim/slide_right"/>
其中
- android:delay表示動畫播放的延時,既可以是百分比,也可以是float小數。
- android:animationOrder表示動畫的播放順序,有三個取值normal(順序)、reverse(反序)、random(隨機)。
- android:animation指向了子控制元件所要播放的動畫。
-
上述步驟完成之後,就可以將layout-animation應用到ViewGroup中,xml佈局新增下面一行就ok:
android:layoutAnimation="@anim/list_anim_layout"
這樣在載入佈局的時候就會自動播放layout-animtion。
程式碼配置
如果在xml中檔案已經寫好LayoutAnimation,可以使用AnimationUtils直接載入:
AnimationUtils.loadLayoutAnimation(context, id)
另外還可以手動java程式碼編寫,如:
//通過載入XML動畫設定檔案來建立一個Animation物件;
Animation animation=AnimationUtils.loadAnimation(this, R.anim.slide_right); //得到一個LayoutAnimationController物件;
LayoutAnimationController controller = new LayoutAnimationController(animation); //設定控制元件顯示的順序;
controller.setOrder(LayoutAnimationController.ORDER_REVERSE); //設定控制元件顯示間隔時間;
controller.setDelay(0.3); //為ListView設定LayoutAnimationController屬性;
listView.setLayoutAnimation(controller);
listView.startLayoutAnimation();
通過程式碼設定可以達到同樣效果。
擴充套件
前幾天遇到一個需求,將動畫順序改為左上到右下角展開,例如Material Design中這個樣子。
雖然一個個按順序播放頁可以實現,但也太low了,就希望能夠找一個簡便的方法。(PS. 個人崇尚簡約就是美)
仔細觀察,很明顯就是一個LayoutAnimation,但是LayoutAnimation預設只有三種順序,即順序逆序和隨機,不能滿足需求。去翻翻原始碼看它是怎麼實現的,有沒有提供方法自定義順序?結果翻到了一個LayoutAnimationController#getTransformedIndex(AnimationParameters params)方法,返回值就是播放動畫的順序。並且這個方法是protected的,明顯就是可由子類來擴充套件。既然找到了方法,那麼就去實現它:
/**
* custom LayoutAnimationController for playing child animation
* in any order.
*
*/
public class CustomLayoutAnimationController extends LayoutAnimationController {
// 7 just lucky number
public static final int ORDER_CUSTOM = 7;
private Callback onIndexListener;
public void setOnIndexListener(OnIndexListener onIndexListener) {
this.onIndexListener = onIndexListener;
}
public CustomLayoutAnimationController(Animation anim) {
super(anim);
}
public CustomLayoutAnimationController(Animation anim, float delay) {
super(anim, delay);
}
public CustomLayoutAnimationController(Context context, AttributeSet attrs) {
super(context, attrs);
}
/**
* override method for custom play child view animation order
*/
protected int getTransformedIndex(AnimationParameters params) {
if(getOrder() == ORDER_CUSTOM && onIndexListener != null) {
return onIndexListener.onIndex(this, params.count, params.index);
} else {
return super.getTransformedIndex(params);
}
}
/**
* callback for get play animation order
*
*/
public static interface Callback{
public int onIndex(CustomLayoutAnimationController controller, int count, int index);
}
}
通過複寫getTransformedIndex方法,新增自定義順序ORDER_CUSTOM,讓callback自定義控制元件播放動畫的順序,即可以達到任何想要的效果。
總結
Android在設計的時候,提供了很好的擴充套件性。各種元件都可以按需求擴充套件。可能用的更多的是還是View.onDraw(Canvas canvas)方法,但不僅僅是view,對於其他元件,也可以隨意的擴充套件。很多時候,並不一定需要自定義很多空間、功能之類的,往往擴充套件一些簡單的元件就能達到自己想要的結果。