Android Animation學習(五) ApiDemos解析:容器布局動畫 LayoutTransition

來源:互聯網
上載者:User

標籤:

Property animation系統還提供了對ViewGroup中的View改變加入動畫的功能。

  你可以使用 LayoutTransition 對ViewGroup中的View改變進行動畫顯示。

  注意,本文所說的動畫效果都是設定給容器(ViewGroup),然而效果是通過容器存放的View來體現的。

 

四種容器轉換動畫類型

  當你添加或者移除ViewGroup中的View時,或者你調用View的setVisibility()方法來控制其顯示或消失時,就處於一個轉換狀態。這種事件就有可能會激發動畫。

  當前被增加或者移除的View可以經曆一個出現的動畫或者一個消失的動畫。

  而且不止是當前要控制的View,ViewGroup中的其他View也可以隨之進行變動,比如經曆一個動畫移動到新的位置。

 

  所以一共有四種相關的動畫類型

  1.View本身的出現動畫;

  2.消失動畫;

  3.由於新增了其他View而需要改變位置的動畫;

  4.由於移除了其他View而需要改變位置的動畫。

  (如果增加或移除了其他View之後,當前View的位置不需要改變,則無動畫)。

 

  你可以自訂這些動畫,通過setAnimator() 方法把它們設定進一個 LayoutTransition 對象中去。

  設定的時候需要一個 Animator 對象和一個常數:

  APPEARING - A flag indicating the animation that runs on items that are appearing in the container.

  CHANGE_APPEARING - A flag indicating the animation that runs on items that are changing due to a new item appearing in the container.

  DISAPPEARING - A flag indicating the animation that runs on items that are disappearing from the container.

  CHANGE_DISAPPEARING - A flag indicating the animation that runs on items that are changing due to an item disappearing from the container.

 

  你可以自己定義這四種事件類型的動畫,也可以使用預設的動畫。

  最後通過setLayoutTransition(LayoutTransition)方法把這些動畫以一個 LayoutTransition 對象的形式設定給一個ViewGroup即可。

  比如下面這個方法就產生了一個全新的LayoutTransition對象並set給容器(ViewGroup類型),這樣四個動畫就全是預設動畫。

 

    // 重建LayoutTransition對象並設定給container    private void resetTransition() {        mTransitioner = new LayoutTransition();        container.setLayoutTransition(mTransitioner);    }

 

  為這個mTransitioner對象產生四個自訂動畫:

 
    // 產生自訂動畫    private void setupCustomAnimations() {        // 動畫:CHANGE_APPEARING        // Changing while Adding        PropertyValuesHolder pvhLeft = PropertyValuesHolder.ofInt("left", 0, 1);        PropertyValuesHolder pvhTop = PropertyValuesHolder.ofInt("top", 0, 1);        PropertyValuesHolder pvhRight = PropertyValuesHolder.ofInt("right", 0,                1);        PropertyValuesHolder pvhBottom = PropertyValuesHolder.ofInt("bottom",                0, 1);        PropertyValuesHolder pvhScaleX = PropertyValuesHolder.ofFloat("scaleX",                1f, 0f, 1f);        PropertyValuesHolder pvhScaleY = PropertyValuesHolder.ofFloat("scaleY",                1f, 0f, 1f);        final ObjectAnimator changeIn = ObjectAnimator.ofPropertyValuesHolder(                this, pvhLeft, pvhTop, pvhRight, pvhBottom, pvhScaleX,                pvhScaleY).setDuration(                mTransitioner.getDuration(LayoutTransition.CHANGE_APPEARING));        mTransitioner.setAnimator(LayoutTransition.CHANGE_APPEARING, changeIn);        changeIn.addListener(new AnimatorListenerAdapter() {            public void onAnimationEnd(Animator anim) {                View view = (View) ((ObjectAnimator) anim).getTarget();                view.setScaleX(1f);                view.setScaleY(1f);            }        });        // 動畫:CHANGE_DISAPPEARING        // Changing while Removing        Keyframe kf0 = Keyframe.ofFloat(0f, 0f);        Keyframe kf1 = Keyframe.ofFloat(.9999f, 360f);        Keyframe kf2 = Keyframe.ofFloat(1f, 0f);        PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe(                "rotation", kf0, kf1, kf2);        final ObjectAnimator changeOut = ObjectAnimator                .ofPropertyValuesHolder(this, pvhLeft, pvhTop, pvhRight,                        pvhBottom, pvhRotation)                .setDuration(                        mTransitioner                                .getDuration(LayoutTransition.CHANGE_DISAPPEARING));        mTransitioner.setAnimator(LayoutTransition.CHANGE_DISAPPEARING,                changeOut);        changeOut.addListener(new AnimatorListenerAdapter() {            public void onAnimationEnd(Animator anim) {                View view = (View) ((ObjectAnimator) anim).getTarget();                view.setRotation(0f);            }        });        // 動畫:APPEARING        // Adding        ObjectAnimator animIn = ObjectAnimator.ofFloat(null, "rotationY", 90f,                0f).setDuration(                mTransitioner.getDuration(LayoutTransition.APPEARING));        mTransitioner.setAnimator(LayoutTransition.APPEARING, animIn);        animIn.addListener(new AnimatorListenerAdapter() {            public void onAnimationEnd(Animator anim) {                View view = (View) ((ObjectAnimator) anim).getTarget();                view.setRotationY(0f);            }        });        // 動畫:DISAPPEARING        // Removing        ObjectAnimator animOut = ObjectAnimator.ofFloat(null, "rotationX", 0f,                90f).setDuration(                mTransitioner.getDuration(LayoutTransition.DISAPPEARING));        mTransitioner.setAnimator(LayoutTransition.DISAPPEARING, animOut);        animOut.addListener(new AnimatorListenerAdapter() {            public void onAnimationEnd(Animator anim) {                View view = (View) ((ObjectAnimator) anim).getTarget();                view.setRotationX(0f);            }        });    }
 

 

 

預設的布局轉換動畫

  如果你要使用預設的動畫,一個非常簡單的方式是在ViewGroup的XML布局檔案中把android:animateLayoutchanges 屬性設定為true。

  這樣就自動地按照預設來對要移除或添加的View,還有Group中的其他View進行動畫。

  比如ApiDemos中的LayoutAnimationsByDefault:

 
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >    <Button        android:id="@+id/addNewButton"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="Add Button" />    <!--    <GridLayout        android:columnCount="4"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:id="@+id/gridContainer"        android:animateLayoutChanges="true"        />    -->    <LinearLayout        android:id="@+id/gridContainer"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:animateLayoutChanges="true"         android:orientation="vertical">    </LinearLayout></LinearLayout>
 

  

  

  我把布局改成了線性布局,只要是ViewGroup類型都可以。

 

  預設情況下,DISAPPEARING和CHANGE_APPEARING動畫是立即開始的,其他動畫都有一個預設的開始延遲。

  這是因為,比如:當一個新的View出現的時候,其他View要立即執行CHANGE_APPEARING動畫騰出位置,而新出現的View在一定延遲之後再執行APPEARING出現;

  相反地,一個View消失的時候,它需要先DISAPPEARING動畫消失,而其他的View需要先等它消失後再執行CHANGE_DISAPPEARING。

  當然這些預設的行為都可以通過 setDuration(int, long) 和setStartDelay(int, long)等方法改變。

 

API Demos代碼

  ApiDemos中布局動畫相關的類有:LayoutAnimationsByDefault 、LayoutAnimations、LayoutAnimationsHideShow。

  完整的項目可以去github下載。https://github.com/mengdd/AnimationApiDemos

 參考資料

  API Guides: Property Animation

  http://developer.android.com/guide/topics/graphics/prop-animation.html

  其中的Animating Layout Changes to ViewGroups

  LayoutTransition類Reference:

  http://developer.android.com/reference/android/animation/LayoutTransition.html

  項目地址:

  https://github.com/mengdd/AnimationApiDemos

Android Animation學習(五) ApiDemos解析:容器布局動畫 LayoutTransition

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.