认识动画(5)-联合动画的代码实现
前言
上篇给大家介绍了ValueAnimator和ObjectAnimator,相比而言ObjectAnimator更为方便而且由于set函数实在控件内部实现,所以封装性更好,而且在现实使用中一般都是首选ObjectAnimator.
但是ValueAnimatior和ObjectAnimator都只能实现一个动画,那我们如果襄阳使用一个组合动画,比如边移动,边改变大小,同时改变颜色.对于这种组合型的动画google为我们提供了一个类AnimatorSet;这篇我们就着重来看看组合动画的实现方法.
AnimatorSet-playSequentially,playTogether
首先,AnimatorSet对ValueAnimator和ObjectAnimator都是适用的,但一般而言,我们不会用到ValueAnimator的组合动画,所以我们接下来只讨论关于ObjectAnimator的组合动画的实现
在AnimatorSet中为我们提供了两个方法playSequentially和playTogether,playSequentially表示所有动画依次播放,playTogether表示所有动画一起开始.
playSequentially
我们先来看看playSequentially的声明:
public void playSequentially(Animator... items);
public void playSequentially(List<Animator> items);
这里有两种声明方法,一种是传输长参数,将动画一个一个的传入,第二种是,将动画装入一个list集合,然后将list传入.
private void doPlaySequentiallyAnimator(){
ObjectAnimator tv1BgAnimator = ObjectAnimator.ofInt(mTv1, "BackgroundColor", 0xffff00ff, 0xffffff00, 0xffff00ff);
ObjectAnimator tv1TranslateY = ObjectAnimator.ofFloat(mTv1, "translationY", 0, 300, 0);
ObjectAnimator tv2TranslateY = ObjectAnimator.ofFloat(mTv2, "translationY", 0, 400, 0);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playSequentially(tv1BgAnimator,tv1TranslateY,tv2TranslateY);
animatorSet.setDuration(1000);
animatorSet.start();
}
playTogether
playTogether表示将所有动画一起播放,我们先来看看playTogether的声明.
public void playTogether(Animator... items);
public void playTogether(Collection<Animator> items);
同样这里也是有两个构造函数,他们的两个的意义是一样的,只是传入的参数不一样,第一个依然是穿可变长参数,第二种同样也是传入一个Collection<Animator>对象.
ObjectAnimator tv1BgAnimator = ObjectAnimator.ofInt(mTv1, "BackgroundColor", 0xffff00ff, 0xffffff00, 0xffff00ff);
ObjectAnimator tv1TranslateY = ObjectAnimator.ofFloat(mTv1, "translationY", 0, 400, 0);
ObjectAnimator tv2TranslateY = ObjectAnimator.ofFloat(mTv2, "translationY", 0, 400, 0);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playTogether(tv1BgAnimator,tv1TranslateY,tv2TranslateY);
animatorSet.setDuration(1000);
animatorSet.start();
playSequentially,playTogether真正意义
想必大家都看过赛马,在赛马开始前,每个马都会被放在栅栏后面,到点了门打开,马开始跑.而假如我们把每匹马看作是一个动画,那我们的playTogether就相当于赛马场的每个赛道上门的意义,等时间一到,所有马一起出发,而playSequentially则有点像接力,所有马排成一队,第一个马出发,第二个马就在出发点等待,直到第一个马到了终点它才会出发,后面的马也是如此.也就是说如果上一匹马一直没到终点,那么这一匹马也一直不会出发.
总的来说,playSequentially和playTogether和只是负责每个动画什么时候开始,除此之外没有任何能力干预到Animator.
自由设置动画顺序-AnimatorSet.Builder
概述
上面我们讲了playTogether和playSequentially,分别能实现一起开始动画和逐个开始动画,但并不是非常自由的组合动画.比如,现在有A B C三个动画我们想先播放C然后同时播放A和B我们想先播放C然后同时播放A和B,利用playTogether和playSequentianlly是没办法实现的,所以为了更方便的组合动画,google的开放人员为我们做准备了AnimatorSet.Buisler;
下面我们实现首先AB一起开始,然后A 运行完毕C开始
ObjectAnimator tv1BgAnimator = ObjectAnimator.ofInt(mTv1, "BackgroundColor", 0xffff00ff, 0xffffff00, 0xffff00ff);
ObjectAnimator tv1TranslateY = ObjectAnimator.ofFloat(mTv1, "translationY", 0, 400, 0);
ObjectAnimator tv1TranslateZ = ObjectAnimator.ofFloat(mTv1, "translationY", 0, 400, 0);
AnimatorSet animatorSet = new AnimatorSet();
AnimatorSet.Builder builder = animatorSet.play(tv1BgAnimator);
builder.with(tv1TranslateY);
builder.after(tv1TranslateZ);
animatorSet.start();
接下来我们详细分析一下两个函数play with
- play
从上面的代码我们可以看出,AnimatorSet.Buider是通过animatorSet.play(tv1BgAnimator)生成的这是生成Animator.Builder对象的唯一途径
public Builder play(Animator anim)
- with
上面代码中我们已经接触到with方法,AnimatorSet方法除了with方法还有许多的其他方法,我们了解一下:
//和前面动画一起执行
public Builder with(Animator anim)
//执行前面的动画后才执行该动画
public Builder before(Animator anim)
//执行先执行这个动画再执行前面动画
public Builder after(Animator anim)
//延迟n毫秒之后执行动画
public Builder after(long delay)
paly(Animator anim)表示当前播放的动画,另外的with,before,after都是以play中的当前所播放的动画为基准的.
上述方法都很好理解,这里要格外注意一点,他们的返回值都是Builder对象,下面有两种使用方式:
- 方式一:使用Buiider对象添加动画
AnimatorSet.Builder builder = animatorSet.play(tv1TranslateY);
builder.with(tv2TranslateY);
builder.after(tv1BgAnimator);
- 方式二:串行方式
animatorSet.play(tv1TranslateY).with(tv2TranslateY).after(tv1BgAnimator);
AnimatorSet监听器
AnimatorSet中也可以添加监听器:
public static interface AnimatorListener {
/**
* 当AnimatorSet开始时调用
*/
void onAnimationStart(Animator animation);
/**
* 当AnimatorSet结束时调用
*/
void onAnimationEnd(Animator animation);
/**
* 当AnimatorSet被取消时调用
*/
void onAnimationCancel(Animator animation);
/**
* 当AnimatorSet重复时调用,由于AnimatorSet没有设置repeat的函数,所以这个方法永远不会被调用
*/
void onAnimationRepeat(Animator animation);
}
通用函数逐个设置与AnimatorSet设置的区别
- 在AnimatorSet中还有几个函数:
//设置单次动画时长
public AnimatorSet setDuration(long duration);
//设置加速器
public void setInterpolator(TimeInterpolator interpolator)
//设置ObjectAnimator动画目标控件
public void setTarget(Object target)
我们都知道在ObjectAnimator中也有着这几个函数,那么AnimatorSet中设置与单个ObjectAnimator中设置有什么区别呢?
区别就是:在AnimatorSet中设置以后,会覆盖单个ObjectAniamtor中的设置;即如果AnimatorSet中没有设置,那么就以ObjectAnimator中的设置为准,如果AniamtorSet设置了以后,ObjectAnimator中的设置就会无效.举例如下:
ObjectAnimator tv1TranslateY = ObjectAnimator.ofFloat(mTv1, "translationY", 0, 400, 0);
tv1TranslateY.setDuration(500000000);
tv1TranslateY.setInterpolator(new BounceInterpolator());
ObjectAnimator tv2TranslateY = ObjectAnimator.ofFloat(mTv2, "translationY", 0, 400, 0);
tv2TranslateY.setInterpolator(new AccelerateDecelerateInterpolator());
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(tv2TranslateY).with(tv1TranslateY);
animatorSet.setDuration(2000);
animatorSet.start();
在上述代码中tv1TranslateY设置了时长为500000000ms,后面又在animatorSet.setDuration(2000);声明了设置,那么最后动画的执行时间应该是2000ms而不是5000000000ms,但是由于AimatorSet中没有给重新设置插值器,那么两个控件将按照自己各自的插值器执行动画.
- setTarget(Object target)
//设置ObjectAnimator动画目标控件
public void setTarget(Object target)
这里我们着重讲Animator的setTarget函数,设个函数用来设置目标控件,也就是说,如果AnimatorSet设置了目标控件,那么所有的动画将在目标动画展示.如下代码:
ObjectAnimator tv1BgAnimator = ObjectAnimator.ofInt(mTv1, "BackgroundColor", 0xffff00ff, 0xffffff00, 0xffff00ff);
ObjectAnimator tv2TranslateY = ObjectAnimator.ofFloat(mTv2, "translationY", 0, 400, 0);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playTogether(tv1BgAnimator,tv2TranslateY);
animatorSet.setDuration(2000);
animatorSet.setTarget(mTv2);
animatorSet.start();
animatorSet.setTarget(mTv2);这句代码将动画的目标设置在了mTv2控件,那么所有的动画都会在tv2执行,mTv1将不会有动画执行.
- setStartDelay(long startDelay)
//设置延时开始动画时长
public void setStartDelay(long startDelay)
上面讲了,当AniamtorSet与ObjectAnimator设置同一属性时,ObjectAnimator设置的会被覆盖,但是setStartDelay是个例外,而且两个都起作用.距离如下代码:
ObjectAnimator tv1TranslateY = ObjectAnimator.ofFloat(mTv1, "translationY", 0, 400, 0);
ObjectAnimator tv2TranslateY = ObjectAnimator.ofFloat(mTv2, "translationY", 0, 400, 0);
tv2TranslateY.setStartDelay(2000);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(tv1TranslateY).with(tv2TranslateY);
animatorSet.setStartDelay(2000);
animatorSet.setDuration(2000);
animatorSet.start();
我们都看到tv2TranslateY.setStartDelay(2000);给tv2TranslateY设置了2000ms的延时,同时在animatorSet.setStartDelay(2000);也为组合动画设置了2000ms的延时,此时动画开始后会先静止2000ms然后tv1TranslateY开始执行,2000ms后tv2TranslateY开始执行.
由此得出结论:
AniamtorSet的延时是仅针对性的延长AniamtorSet激活事件的,对单个动画的延时设置没有影响.
文章来源:
http://blog.csdn.net/harvic880925/article/details/50759059