Android 动画(七)AnimatorSet组合动画

概述:

ValueAnimator和ObjectAnimator都是针对单个动画的,虽然可以用PropertyValuesHolder实现一个View的多种动画,但是没办法实现多个View同时动画。如果要对多个View做动画,并且单个View上存在多种动画效果,这时候就要用到AnimatorSet类了。AnimatorSet类用来实现复杂的组合动画,但功能上相比于AnimationSet强大多了。AnimatorSet针对ValueAnimator和ObjectAnimator都是适用的,但一般而言,基本不会用到ValueAnimator的组合动画。

一、AnimatorSet

在AnimatorSet中给为我们提供了两个方法playSequentially和playTogether,

  • playSequentially表示所有动画依次播放
  • playTogether表示所有动画一起开始

1.1 playSequentially

playSequentially的声明如下:

public void playSequentially(Animator... items);
public void playSequentially(List items);

这里有两个声明方法,第一个是最常用的,它的参数是可变长参数,也就是说我们可以传进去任意多个Animator对象。这些对象的动画会逐个播放。
第二个构造方法,是传进去一个List< Animator>的列表。原理一样,也是逐个去取List中的动画对象,然后逐个播放。
下面代码演示使用第一种构造方法:

    /*** 设置多个View顺序播放动画**/private void startPlaySequentiallyAnim() {ObjectAnimator objectAnimator01 = ObjectAnimator.ofArgb(ivImage01, "BackgroundColor",getResources().getColor(R.color.colorPrimary),getResources().getColor(R.color.colorAccent),getResources().getColor(R.color.colorPrimary));ObjectAnimator objectAnimator02 = ObjectAnimator.ofFloat(ivImage01, "TranslationY", 0, 300, 0);ObjectAnimator objectAnimator03 = ObjectAnimator.ofFloat(ivImage02, "TranslationY", 0, 400, 0);ObjectAnimator objectAnimator04 = ObjectAnimator.ofFloat(ivImage03, "TranslationY", 0, 500, 0);ObjectAnimator objectAnimator05 = ObjectAnimator.ofFloat(ivImage04, "TranslationY", 0, 600, 0);AnimatorSet animatorSet=new AnimatorSet();animatorSet.playSequentially(objectAnimator01,objectAnimator02,objectAnimator03,objectAnimator04,objectAnimator05);animatorSet.setDuration(2000);animatorSet.start();}

效果如下:
这里写图片描述

1.2 playTogether

playTogether表示将所有动画一起播放
playTogether的声明如下:

public void playTogether(Animator... items);
public void playTogether(Collection items);

有两个声明方法,区别只是传入的参数不一样
第一个是传可变长参数列表
第二个则是需要传一个组装好的Collection对象。
下面代码演示使用第一种构造方法:

    /*** 设置多个View一起播放动画*/private void startPlayTogetherAnim() {ObjectAnimator objectAnimator01 = ObjectAnimator.ofArgb(ivImage05, "BackgroundColor",getResources().getColor(R.color.colorPrimary),getResources().getColor(R.color.colorAccent),getResources().getColor(R.color.colorPrimary));ObjectAnimator objectAnimator02 = ObjectAnimator.ofFloat(ivImage05, "TranslationY", 0, 300, 0);ObjectAnimator objectAnimator03 = ObjectAnimator.ofFloat(ivImage06, "TranslationY", 0, 400, 0);ObjectAnimator objectAnimator04 = ObjectAnimator.ofFloat(ivImage07, "TranslationY", 0, 500, 0);ObjectAnimator objectAnimator05 = ObjectAnimator.ofFloat(ivImage08, "TranslationY", 0, 600, 0);AnimatorSet animatorSet = new AnimatorSet();animatorSet.playTogether(objectAnimator01, objectAnimator02, objectAnimator03, objectAnimator04, objectAnimator05);animatorSet.setDuration(2000);animatorSet.start();}

动画效果:

这里写图片描述

实现无限循环动画:

示例代码:

    /*** 设置多个View一起播放无限循环动画*/private AnimatorSet startInfiniteLoopAnim() {ObjectAnimator objectAnimator01 = ObjectAnimator.ofArgb(ivImage09, "BackgroundColor",getResources().getColor(R.color.colorPrimary),getResources().getColor(R.color.colorAccent),getResources().getColor(R.color.colorPrimary));objectAnimator01.setRepeatCount(ValueAnimator.INFINITE);ObjectAnimator objectAnimator02 = ObjectAnimator.ofFloat(ivImage09, "TranslationY", 0, 300, 0);objectAnimator02.setRepeatCount(ValueAnimator.INFINITE);ObjectAnimator objectAnimator03 = ObjectAnimator.ofFloat(ivImage10, "TranslationY", 0, 400, 0);objectAnimator03.setRepeatCount(ValueAnimator.INFINITE);ObjectAnimator objectAnimator04 = ObjectAnimator.ofFloat(ivImage11, "TranslationY", 0, 500, 0);objectAnimator04.setRepeatCount(ValueAnimator.INFINITE);ObjectAnimator objectAnimator05 = ObjectAnimator.ofFloat(ivImage12, "TranslationY", 0, 600, 0);objectAnimator05.setRepeatCount(ValueAnimator.INFINITE);AnimatorSet animatorSet = new AnimatorSet();animatorSet.playTogether(objectAnimator01, objectAnimator02, objectAnimator03, objectAnimator04, objectAnimator05);animatorSet.setDuration(2000);animatorSet.start();return animatorSet;}

动画效果:
这里写图片描述

playTogether和playSequentially在激活动画后,控件的动画情况与它们无关,它们只负责定时激活控件动画。
playSequentially只有上一个控件做完动画以后,才会激活下一个控件的动画,如果上一控件的动画是无限循环,那下一个控件就无法做动画了。

1.3 AnimatorSet.Builder(自由设置动画顺序)

AnimatorSet.Builder用于实现playTogether和playSequentially无法实现的效果,可以实现非常自由的组合动画,比如有三个动画A,B,C想先播放C然后同时播放A和B,利用playTogether和playSequentially是没办法实现的,但利用AnimatorSet.Builder却可以轻易实现。

1.3.1 AnimatorSet.Builder常用方法
方法概述
public Builder play(Animator anim)表示要播放哪个动画
AnimatorSet中的play方法是获取AnimatorSet.Builder对象的唯一途径
public Builder with(Animator anim)和前面动画一起执行
public Builder before(Animator anim)执行前面的动画后才执行该动画
public Builder after(Animator anim)执行先执行这个动画再执行前面动画
public Builder after(long delay)延迟n毫秒之后执行动画

play(Animator anim)表示当前在播放哪个动画,另外的with(Animator anim)、before(Animator anim)、after(Animator anim)都是以play中的当前所播放的动画为基准的。
当play(playAnim)与before(beforeAnim)共用,则表示在播放beforeAnim之前,先播放playAnim动画;同样,当play(playAnim)与after(afterAnim)共用时,则表示在在播放afterAnim动画之后,再播放playAnim动画。

示例代码:

    /*** 按照自定义顺序播放动画* 首先ivImage09的颜色变化、位移和ivImage09,同时发生* 等待前面的动画播放完后 ivImage11,ivImage12才开始动画**/private void startCustomOrderAnim() {ObjectAnimator objectAnimator01=ObjectAnimator.ofArgb(ivImage09, "BackgroundColor",getResources().getColor(R.color.colorPrimary),getResources().getColor(R.color.colorAccent),getResources().getColor(R.color.colorPrimary));ObjectAnimator objectAnimator02 = ObjectAnimator.ofFloat(ivImage09, "TranslationY", 0, 300, 0);ObjectAnimator objectAnimator03 = ObjectAnimator.ofFloat(ivImage10, "TranslationY", 0, 400, 0);ObjectAnimator objectAnimator04 = ObjectAnimator.ofFloat(ivImage11, "TranslationY", 0, 500, 0);ObjectAnimator objectAnimator05 = ObjectAnimator.ofFloat(ivImage12, "TranslationY", 0, 600, 0);AnimatorSet animatorSet = new AnimatorSet();animatorSet.play(objectAnimator01).with(objectAnimator02).with(objectAnimator03).before(objectAnimator04).before(objectAnimator05);animatorSet.setDuration(2000);animatorSet.start();}

动画效果:
这里写图片描述

1.4 AnimatorSet监听器

在AnimatorSet中也可以添加监听器,添加方法为:
public void addListener(AnimatorListener listener);

AnimatorSet的监听:

  • AnimatorSet的监听函数也只是用来监听AnimatorSet的状态的,与其中的动画无关;
  • AnimatorSet中没有设置循环的函数,所以AnimatorSet监听器中永远无法运行到onAnimationRepeat()中!
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);
}

1.5 AnimatorSet常用方法

方法概述
public AnimatorSet setDuration(long duration)设置单次动画时长
public void setInterpolator(TimeInterpolator interpolator)设置插值器
public void setTarget(Object target)设置ObjectAnimator动画目标控件
public void setStartDelay(long startDelay)设置AnimatorSet动画延迟激活时间

由于在ObjectAnimator中也存在以上方法,在AnimatorSet中设置以后,会覆盖单个ObjectAnimator中的设置;即如果AnimatorSet中没有设置,那么就以ObjectAnimator中的设置为准。如果AnimatorSet中设置以后,ObjectAnimator中的设置就会无效。例如:AnimatorSet.setTarget()的作用就是将动画的目标统一设置为当前控件,AnimatorSet中的所有动画都将作用在所设置的target控件上。但唯一的例外就是setStartDelay。
setStartDelay函数不会覆盖单个动画的延时,而且仅针对性的延长AnimatorSet的激活时间,单个动画的所设置的setStartDelay仍对单个动画起作用。

注意:

  1. AnimatorSet的延时是仅针对性的延长AnimatorSet激活时间的,对单个动画的延时设置没有影响。
  2. 在使用with的情况下,AnimatorSet的激活时间跟单个动画没有关系,激活后所有动画同时开始,包括延迟

下面两个例子可以好好体会下:

    /***  animatorSet 设置激活动画延时时长我们首先给animatorSet设置了2秒后开始激活动画,而objectAnimator02设置了2秒启动延时,objectAnimator03/04/05都没有设置延时所以objectAnimator02在animatorSet激活动画2秒后才会运动,objectAnimator03/04/05在animatorSet激活动画后,就会开始运动。*/private void startDelay01Anim() {ObjectAnimator objectAnimator02 = ObjectAnimator.ofFloat(ivImage09, "TranslationY", 0, 300, 0);objectAnimator02.setStartDelay(2000);ObjectAnimator objectAnimator03 = ObjectAnimator.ofFloat(ivImage10, "TranslationY", 0, 400, 0);ObjectAnimator objectAnimator04 = ObjectAnimator.ofFloat(ivImage11, "TranslationY", 0, 500, 0);ObjectAnimator objectAnimator05 = ObjectAnimator.ofFloat(ivImage12, "TranslationY", 0, 600, 0);AnimatorSet animatorSet = new AnimatorSet();animatorSet.play(objectAnimator02).with(objectAnimator03).with(objectAnimator04).with(objectAnimator05);animatorSet.setStartDelay(2000);animatorSet.setDuration(2000);animatorSet.start();}

这里写图片描述



   /***  animatorSet 设置激活动画延时时长我们首先给animatorSet设置了2秒后激活动画,而objectAnimator02没有设置启动延时,所以在animatorSet激活动画后objectAnimator02马上开始运动,而objectAnimator03/04/05都设置2秒启动延时,并跟随objectAnimator02一起运动,所以会在animatorSet激活动画并延时2秒后,才开始动画。*/private void startDelay02Anim() {ObjectAnimator objectAnimator02 = ObjectAnimator.ofFloat(ivImage09, "TranslationY", 0, 300, 0);ObjectAnimator objectAnimator03 = ObjectAnimator.ofFloat(ivImage10, "TranslationY", 0, 400, 0);objectAnimator03.setStartDelay(2000);ObjectAnimator objectAnimator04 = ObjectAnimator.ofFloat(ivImage11, "TranslationY", 0, 500, 0);objectAnimator04.setStartDelay(2000);ObjectAnimator objectAnimator05 = ObjectAnimator.ofFloat(ivImage12, "TranslationY", 0, 600, 0);objectAnimator05.setStartDelay(2000);AnimatorSet animatorSet = new AnimatorSet();animatorSet.play(objectAnimator02).with(objectAnimator03).with(objectAnimator04).with(objectAnimator05);animatorSet.setStartDelay(2000);animatorSet.setDuration(2000);animatorSet.start();}

这里写图片描述

二、AnimatorSet XML实现

2.1 xml标签与java类的对应关系

XML标签java类
ValueAnimator
ObjectAnimator
AnimatorSet

2.2 animator字段详解

--
android:duration=”int”
ndroid:valueFrom=”float | int | color”
ndroid:valueTo=”float | int | color”
ndroid:startOffset=”int”
ndroid:repeatCount=”int”
ndroid:repeatMode=[“repeat” | “reverse”]
ndroid:valueType=[“intType” | “floatType”]
ndroid:interpolator=[“@android:anim/xxx”]/>
android:duration:每次动画播放的时长
android:valueFrom:初始动化值;取值范围为float,int和color,如果取值为float对应的值样式应该为89.0,取值为Int时,对应的值样式为:89;当取值为clolor时,对应的值样式为 #333333;
android:valueTo:动画结束值;取值范围同样是float,int和color这三种类型的值;
android:startOffset:动画激活延时;对应代码中的startDelay(long delay)函数;
android:repeatCount:动画重复次数
android:repeatMode:动画重复模式,取值为repeat和reverse;repeat表示正序重播,reverse表示倒序重播
android:valueType:表示参数值类型,取值为intType和floatType;与android:valueFrom、android:valueTo相对应。如果这里的取值为intType,那么android:valueFrom、android:valueTo的值也就要对应的是int类型的数值。如果这里的数值是floatType,那么android:valueFrom、android:valueTo的值也要对应的设置为float类型的值。
注意:如果android:valueFrom、android:valueTo的值设置为color类型的值,那么不需要设置这个参数;
android:interpolator:设置加速器/插值器;

示例代码:
animator/anim_animator.xml:


<animator xmlns:android="http://schemas.android.com/apk/res/android"android:duration="1000"android:valueType="floatType"android:valueFrom="0.1"android:valueTo="1.0"android:interpolator="@android:anim/bounce_interpolator">
animator>
    /*** 使用AnimatorInflater.loadAnimator()加载xml中定义的ValueAnimator动画*/private void loadXmlAnimator(){ValueAnimator valueAnimator=(ValueAnimator) AnimatorInflater.loadAnimator(this,R.animator.anim_animator);valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {float value=(float)animation.getAnimatedValue();ivImage01.setScaleX(value);ivImage01.setScaleY(value);}});valueAnimator.start();}

动画效果:
这里写图片描述

2.3 objectAnimator字段详解

--
objectAnimatorndroid:propertyName=”string”
ndroid:duration=”int”
ndroid:valueFrom=”float | int |color”
ndroid:valueTo=”float | int | color”
ndroid:startOffset=”int”
ndroid:repeatCount=”int”
ndroid:repeatMode=[“repeat” | “reverse”]
ndroid:valueType=[“intType” | “floatType”]
ndroid:interpolator=[“@android:anim/xxx”]/>
android:propertyName:对应属性名,即ObjectAnimator所需要操作的属性名。
android:duration:每次动画播放的时长
android:valueFrom:初始动化值;取值范围为float,int和color;
android:valueTo:动画结束值;取值范围同样是float,int和color这三种类型的值;
android:startOffset:动画激活延时;对应代码中的startDelay(long delay)函数;
android:repeatCount:动画重复次数
android:repeatMode:动画重复模式,取值为repeat和reverse;repeat表示正序重播,reverse表示倒序重播
android:valueType:表示参数值类型,取值为intType和floatType;与android:valueFrom、android:valueTo相对应。如果这里的取值为intType,那么android:valueFrom、android:valueTo的值也就要对应的是int类型的数值。如果这里的数值是floatType,那么android:valueFrom、android:valueTo的值也要对应的设置为float类型的值。非常注意的是,如果android:valueFrom、android:valueTo的值设置为color类型的值,那么不需要设置这个参数;
android:interpolator:设置加速器;

示例代码01:
animator/anim_object_animator.xml


<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"android:duration="1500"android:propertyName="TranslationX"android:valueFrom="0"android:valueTo="400"android:interpolator="@android:anim/accelerate_decelerate_interpolator"android:repeatCount="1"android:repeatMode="reverse"android:startOffset="1000">
objectAnimator>

java:

    /*** 使用AnimatorInflater.loadAnimator()加载xml中定义的ObjectAnimator动画*/private void loadXmlObjectAnimator(){ObjectAnimator objectAnimator=(ObjectAnimator) AnimatorInflater.loadAnimator(this,R.animator.anim_object_animator);objectAnimator.setTarget(ivImage02);objectAnimator.start();}

动画效果:
这里写图片描述

示例代码02:
animator/anim_object_animator_color.xml


<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"android:duration="2000"android:propertyName="BackgroundColor"android:valueFrom="@color/colorAccent"android:valueTo="@color/colorPrimary"android:repeatCount="1"android:repeatMode="reverse">objectAnimator>

java代码:

    /*** 使用AnimatorInflater.loadAnimator()加载xml中定义的ObjectAnimator color动画*/private void loadXmlObjectAnimatorColor(){ObjectAnimator objectAnimator=(ObjectAnimator) AnimatorInflater.loadAnimator(this,R.animator.anim_object_animator_color);objectAnimator.setEvaluator(new ArgbEvaluator());objectAnimator.setTarget(ivImage02);objectAnimator.start();}

动画效果:
这里写图片描述

2.4 set字段详解

字段意义及使用方法

--
android:ordering[“together” |”sequentially”]
android:ordering:表示动画开始顺序。together表示同时开始动画,sequentially表示逐个开始动画;

示例代码:
animator/anim_animator_set.xml


<set xmlns:android="http://schemas.android.com/apk/res/android"android:ordering="together"><objectAnimator android:duration="1500"android:propertyName="TranslationX"android:valueFrom="0"android:valueTo="400"android:interpolator="@android:anim/accelerate_decelerate_interpolator"android:repeatCount="1"android:repeatMode="reverse"android:startOffset="1000"/><objectAnimator android:duration="2000"android:propertyName="BackgroundColor"android:valueFrom="@color/colorAccent"android:valueTo="@color/colorPrimary"android:repeatCount="1"android:repeatMode="reverse"android:valueType="colorType"/>set>

java代码:

    /*** 使用AnimatorInflater.loadAnimator()加载xml中定义的AnimatorSet动画*/private void loadXmlAnimatorSet(){AnimatorSet animatorSet=(AnimatorSet) AnimatorInflater.loadAnimator(this,R.animator.anim_animator_set);animatorSet.setTarget(ivImage02);animatorSet.start();}

动画效果:
这里写图片描述




到此Android的动画部分,就学习完结了,总共7篇,由浅至深的学习了android的动画部分,当然了只是一些基础部分,剩下还要在实战中继续提高。(PS:虽然动画部分上个月就学习完了,但由于时间紧张,工作也比较忙,间隔一个月后才陆陆续续的总结完毕。),后续也会在博客中放一些动画例子。


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部