ViewGroup整体子view动画设置

1:LayoutAnimationController用于一个布局或者ViewGroup的动画控制器,它能够让每个子View在不同的时间点分别执行相同的动画,ViewGroup通过LayoutAnimationController计算每个子view的动画开始的时间间隔,这个时间的间隔是通过某种规律特点进行计算,比如它在viewGroup中的index顺序。

  • LayoutAnimation_delay:延迟时间
  • LayoutAnimation_animationOrder:动画播放顺序
  • LayoutAnimation_interpolator:动画的差值,有加速,减速等
  • LayoutAnimation_animation:动画的名称


二、动画播放顺序

LayoutAnimationController类中对应的播放顺序:

  • public static final int ORDER_NORMAL = 0:按照view添加到view group中的顺序进行播放动画展示
  • public static final int ORDER_REVERSE = 1;按照view添加到view group中倒叙进行播放动画展示。
  • public static final int ORDER_RANDOM = 2;随机顺序播放view的动画。

我们如何构建一个LayoutAnimationController呢?看下它的构造函数。

  • public LayoutAnimationController(Context context, AttributeSet attrs)
  • public LayoutAnimationController(Animation animation)
  • public LayoutAnimationController(Animation animation, float delay)


1、判断两个view之间的动画是否具有重叠,重叠返回true,不重叠返回false

    public boolean willOverlap() {
        return mDelay < 1.0f;
    }
  • 1
  • 2
  • 3

2、启动动画:

    public void start() {
        mDuration = mAnimation.getDuration();
        mMaxDelay = Long.MIN_VALUE;
        mAnimation.setStartTime(-1);
    }
  • 1
  • 2
  • 3
  • 4
  • 5

3、获取应用在view上的Animation动画对象:

    public final Animation getAnimationForView(View view) {
        final long delay = getDelayForView(view) + mAnimation.getStartOffset();
        mMaxDelay = Math.max(mMaxDelay, delay);

        try {
            final Animation animation = mAnimation.clone();
            animation.setStartOffset(delay);
            return animation;
        } catch (CloneNotSupportedException e) {
            return null;
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

4、判断动画是否完成:所有子view完成动画返回true,否则返回false

    public boolean isDone() {
        return AnimationUtils.currentAnimationTimeMillis() >
                mAnimation.getStartTime() + mMaxDelay + mDuration;
    }


5、获取view的动画延迟数:

    /**
         * 返回view的动画延迟毫秒数,动画一定会延迟,子类需要重写该方法,来
         * 计算返回一个数
         * child animation delay = child index * delay
         *
         * index序列从ViewGroup.LayoutParams的AnimationParameters中获取
         */
        protected long getDelayForView(View view) {
            //获取view的LayoutParams
            ViewGroup.LayoutParams lp = view.getLayoutParams();
            //在LayoutParams属性中获取view的AnimationParameters
            AnimationParameters params = lp.layoutAnimationParameters;
            //判断AnimationParameters是否为空
            if (params == null) {
                return 0;
            }
            //计算动画的延迟时间delay * duration
            final float delay = mDelay * mAnimation.getDuration();
            //计算view的延迟时间index * delay
            final long viewDelay = (long) (getTransformedIndex(params) * delay);
            //view的全部延迟时间delay * count
            final float totalDelay = delay * params.count;
            //动画的插值器是否为空
            if (mInterpolator == null) {
                mInterpolator = new LinearInterpolator();
            }

            float normalizedDelay = viewDelay / totalDelay;
            normalizedDelay = mInterpolator.getInterpolation(normalizedDelay);

            return (long) (normalizedDelay * totalDelay);
        }
  • 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

6、获取变换的index顺序

    /**
         * 变换的index值存储在AnimationParameters对象中
         * 子类需要重写这个方法来提供额外的不同顺序。
         * 该方法被getDelayForView(android.view.View)调用
         */
        protected int getTransformedIndex(AnimationParameters params) {
            switch (getOrder()) {
                case ORDER_REVERSE:
                    return params.count - 1 - params.index;
                case ORDER_RANDOM:
                    if (mRandomizer == null) {
                        mRandomizer = new Random();
                    }
                    return (int) (params.count * mRandomizer.nextFloat());
                case ORDER_NORMAL:
                default:
                    return params.index;
            }
        }

针对上面的几个主要方法的源码分析,我们知道如果我们自定义一个LayoutAnimationController,需要我们控制顺序,控制顺序就需要我们重写getTransformedIndex()方法,我们通过AnimationParameters类中的属性进行index的计算。然后由getDelayForView()方法计算每个view的延迟时间。


案例三、GridView动画效果

在上一篇博客中,我们了解到GridLayoutAnimationController是一个针对GridView之类具有行列性质控件使用的,所以这篇我们就简要的看看他的效果。既然具有行列性质,那么它的运动方向就比较多。可以同时设置多个方向进行操作。

  • public static final int DIRECTION_LEFT_TO_RIGHT = 0x0;从左到右
  • public static final int DIRECTION_RIGHT_TO_LEFT = 0x1;从右到左
  • public static final int DIRECTION_TOP_TO_BOTTOM = 0x0;从上到下
  • public static final int DIRECTION_BOTTOM_TO_TOP = 0x2;从下到上
  • public static final int DIRECTION_HORIZONTAL_MASK = 0x1;水平方向
  • public static final int DIRECTION_VERTICAL_MASK = 0x2;竖直方向

还有一个问题,就是行列优先级问题。通过函数setDirectionPriority()进行设定。

  • public static final int PRIORITY_NONE = 0;行列同级,默认值
  • public static final int PRIORITY_COLUMN = 1;列优先
  • public static final int PRIORITY_ROW = 2;行优先

动画我们还是采用上面的从下到上的动画,只需要看看使用代码即可。


gridView = (GridView) findViewById(R.id.gridView);

gridView.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_expandable_list_item_1, getData()));

GridLayoutAnimationController gridLayoutAnimationController = new GridLayoutAnimationController(

AnimationUtils.loadAnimation(getApplication(),R.anim.bottom_in));

//设置动画播放顺序

gridLayoutAnimationController.setOrder(LayoutAnimationController.ORDER_NORMAL);

//设置动画播放方向

gridLayoutAnimationController.setDirection(GridLayoutAnimationController.DIRECTION_LEFT_TO_RIGHT);

//设置动画播放顺序的优先级

gridLayoutAnimationController.setDirectionPriority(GridLayoutAnimationController.PRIORITY_NONE);

gridView.setLayoutAnimation(gridLayoutAnimationController);

gridView.startLayoutAnimation();


案例四、自定义LayoutAnimationController

看下我们的目标效果图:

接着就是我们的自定义LayoutAnimationController。

public class MyLayoutAnimationController extends LayoutAnimationController {

public static final int ORDER_CUSTOM  = 6;

public MyLayoutAnimationController(Animation anim) {
    super(anim);
}

public MyLayoutAnimationController(Animation anim, float delay) {
    super(anim, delay);
}

public MyLayoutAnimationController(Context context, AttributeSet attrs) {
    super(context, attrs);
}


protected int getTransformedIndex(AnimationParameters params) {
    if(getOrder() == ORDER_CUSTOM){//view顺序以1开头
        if(params.index == 2)return 4;
        else if(params.index == 3)return 5;
        else if(params.index == 4)return 2;
        else if(params.index == 5)return 6;
        else if(params.index == 6)return 3;
        else return params.index;
    }else{
        return super.getTransformedIndex(params);
    }
}

}


eg:

li= (LinearLayout) findViewById(R.id.rl);
anim=new AlphaAnimation(0,1);
anim.setInterpolator(new LinearInterpolator());
anim.setDuration(200);
anim.setFillAfter(true);
cont=new LayoutAnimationController(anim);
cont.setInterpolator(new LinearInterpolator());
cont.setOrder(LayoutAnimationController.ORDER_RANDOM);
but= (Button) findViewById(R.id.but);
for(int i=0;i<5;i++){
    TextView tv=new TextView(SecondActivity.this);
    Log.d(TAG, "onClick: i=="+i);
    tv.setText(i+"==ii");
    li.addView(tv);
}
but.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        li.setLayoutAnimation(cont);
        li.startLayoutAnimation();
    }
});
























































评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值