安卓文档

认识动画(5)-联合动画的代码实现

2018-03-15  本文已影响13人  小庄bb

前言

上篇给大家介绍了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

public Builder play(Animator anim)
//和前面动画一起执行
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对象,下面有两种使用方式:

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设置的区别

  1. 在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中没有给重新设置插值器,那么两个控件将按照自己各自的插值器执行动画.

  1. 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将不会有动画执行.

  1. 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

上一篇 下一篇

猜你喜欢

热点阅读