Android Animation学習(五)ApiDemos解析:コンテナレイアウトアニメーションLayoutTransition

15024 ワード


Android Animation学習(五)ApiDemos解析:コンテナレイアウトアニメーションLayoutTransition
 
Property animationシステムでは、ViewGroupのViewを変更してアニメーションを追加する機能も提供されています.LayoutTransitionを使用して、ViewGroupのViewの変更をアニメーション表示できます.
なお、本明細書でいうアニメーション効果はいずれもコンテナに設定されているが、効果はコンテナに格納されたViewによって現れる.
 
4種類のコンテナ変換アニメーションタイプ
ビューグループのビューを追加または削除するとき、またはビューのsetVisibility()メソッドを呼び出して表示または消失を制御すると、変換状態になります.このイベントはアニメーションを刺激する可能性があります.
現在追加または削除されているViewは、出現したアニメーションまたは消失したアニメーションを経験することができる.
また、現在制御されているViewだけでなく、View Group内の他のViewも、アニメーションを経験して新しい位置に移動するなど、変更することができます.
 
関連するアニメーションの種類は全部で4種類あります.
  1.ビュー自体の出現アニメーション;
  2.アニメーションを消す;
  3.他のビューが追加されたため、位置を変更する必要があるアニメーション.
  4.他の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.
 
この4つのイベントタイプのアニメーションを自分で定義したり、デフォルトのアニメーションを使用したりすることができます.
最後に、setLayoutTransition(LayoutTransition)の方法でこれらのアニメーションを1つのLayoutTransitionオブジェクトの形で1つのViewGroupに設定すればよい.
たとえば、次の方法では、新しいLayoutTransitionオブジェクトが生成され、コンテナ(ViewGroupタイプ)にセットされます.これにより、4つのアニメーションはすべてデフォルトのアニメーションになります.
 
    //     LayoutTransition      container
    private void resetTransition() {
        mTransitioner = new LayoutTransition();
        container.setLayoutTransition(mTransitioner);
    }

 
このmTransitionrオブジェクトのカスタムアニメーションを4つ作成します.
    //        
    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に設定するのが簡単です.
これにより、削除または追加するビュー、およびグループ内の他のビューを自動的にデフォルトでアニメーション化します.
例えば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が現れます;
逆に、1つの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 ViewGroup
LayoutTransitionクラスReference:
   http://developer.android.com/reference/android/animation/LayoutTransition.html
プロジェクトのアドレス:
   https://github.com/mengdd/AnimationApiDemos