布局动画

给ViewGroup设置childView改变时的动画,即ViewGroup布局改变时的动画。

  1. ViewGroup.setLayoutAnimation()方法与android:layoutAnimation=""属性。
    这两种方式是用来给当前ViewGroup设置属性动画的,但是这个属性动画只是在ViewGroup初次创建的时候生效。
    看ViewGroup.setLayoutAnimation的源码注视,明确指定了first layout。但是我们可以通过ViewGroup的scheduleLayoutAnimation()或者startLayoutAnimation()在需要的时候再次执行该布局动画。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    /**
    * Sets the layout animation controller used to animate the group's
    * children after the first layout. *
    * @param controller the animation controller
    */
    public void setLayoutAnimation(LayoutAnimationController controller) {
    mLayoutAnimationController = controller;
    if (mLayoutAnimationController != null) {
    mGroupFlags |= FLAG_RUN_ANIMATION;
    }
    }

常用API介绍:

  • ViewGroup.setLayoutAnimation(LayoutAnimationController controller) :给ViewGroup设置布局动画,
  • ViewGroup.scheduleLayoutAnimation():此方法再次播放该属性动画
  • ViewGroup.startLayoutAnimation():此方法再次播放该属性动画,与scheduleLayoutAnimation()不同的是会强制进行一次布局
  • LayoutAnimationController:对xml中layoutAnimation动画标签的封装,功能和layoutAnimation标签相同。
    使用过程中可以通过构造方法获取,或者通过AnimationUtils.loadLayoutAnimation()方法加载xml中的 layoutAnimation动画。
  • LayoutAnimationController.setOrder(LayoutAnimationController.ORDER_NORMAL);
  • LayoutAnimationController.setDelay();
    1.1 具体实例:

/animation.gif)

  • 方式一:使用xml的方式:使用ViewGroup的layoutAnimation属性,给此属性指定一个layoutAnimation
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    //layoutAnimation使用xml创建要已layoutAnimation标签开始
    //animationOrder表示出现子View的顺序,有normal(正常顺序),reverse(逆序),random(随机顺序)
    //android:animation:需要指定一个你想要让childView执行的动画
    //delay:表示延迟执行
    //interpolator:动画插值器,可以给layoutAnimation指定动画插值器
    <?xml version="1.0" encoding="utf-8"?>
    <layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
    android:animationOrder="normal"
    android:animation="@anim/translate"
    android:delay="0.5"
    android:interpolator="@android:anim/accelerate_interpolator">
    </layoutAnimation>
1
2
3
4
5
6
7
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta="0" android:toXDelta="0"
android:fromYDelta="100%p" android:toYDelta="0"
android:duration = "700"
android:interpolator="@android:anim/overshoot_interpolator">
</translate>
1
2
3
4
5
6
7
8
9
10
11
<GridView
android:id="@+id/grid_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:columnWidth="60dp"
android:gravity="center"
android:numColumns="auto_fit"
android:stretchMode="columnWidth"
android:verticalSpacing="10dp"
android:animateLayoutChanges="false"
android:layoutAnimation="@anim/layout_animation_translate"></GridView>
  • 方式二:代码中使用LayoutAnimationController设置
    1
    2
    3
    4
    5
    6
        private void setLayoutAnimation(ViewGroup viewGroup) {
    LayoutAnimationController layoutAnimationController = AnimationUtils.loadLayoutAnimation(this, R.anim.layout_animation_translate);
    layoutAnimationController.setOrder(LayoutAnimationController.ORDER_NORMAL);
    // layoutAnimationController.setDelay();
    viewGroup.setLayoutAnimation(layoutAnimationController);
    }

扩展 自定义布局动画执行的顺序

想自定义布局动画的顺序,只需要继承LayoutAnimationController,并复写getTransformedIndex(AnimationParameters params)方法即可。
具体实例:参考http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0619/3090.html
/1442313422121422.gif)

仔细观察,很明显就是一个LayoutAnimation,但是LayoutAnimation默认只有三种顺序,即顺序逆序和随机,不能满足需求。去翻翻源码看它是怎么实现的,有没有提供方法自定义顺序?结果翻到了一个LayoutAnimationController#getTransformedIndex(AnimationParameters params)方法,返回值就是播放动画的顺序。并且这个方法是protected的,明显就是可由子类来扩展。既然找到了方法,那么就去实现它:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
/**
* 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自定义控件播放动画的顺序,即可以达到任何想要的效果。