概述:
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<Animator> 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<Animator> 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仍对单个动画起作用。
注意:
- AnimatorSet的延时是仅针对性的延长AnimatorSet激活时间的,对单个动画的延时设置没有影响。
- 在使用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类 |
---|---|
<animator /> | ValueAnimator |
<objectAnimator /> | ObjectAnimator |
<set /> | AnimatorSet |
2.2 animator字段详解
- | - |
---|---|
<animator/> | <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:
<?xml version="1.0" encoding="utf-8"?>
<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字段详解
- | - |
---|---|
objectAnimator | <objectAnimator ndroid: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
<?xml version="1.0" encoding="utf-8"?>
<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
<?xml version="1.0" encoding="utf-8"?>
<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
<?xml version="1.0" encoding="utf-8"?>
<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:虽然动画部分上个月就学习完了,但由于时间紧张,工作也比较忙,间隔一个月后才陆陆续续的总结完毕。),后续也会在博客中放一些动画例子。