1. 程式人生 > >Layout動畫:在android佈局發生變化時新增動畫效果

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"/>

其中

  1. android:delay表示動畫播放的延時,既可以是百分比,也可以是float小數。
  2. android:animationOrder表示動畫的播放順序,有三個取值normal(順序)、reverse(反序)、random(隨機)。
  3. android:animation指向了子控制元件所要播放的動畫。

  4. 上述步驟完成之後,就可以將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 &amp;&amp; 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,對於其他元件,也可以隨意的擴充套件。很多時候,並不一定需要自定義很多空間、功能之類的,往往擴充套件一些簡單的元件就能達到自己想要的結果。