ValueAnimator和ObjectAnimator都是针对单个动画的,虽然可以用PropertyValuesHolder实现一个View的多种动画,但是没办法实现多个View同时动画。如果要对多个View做动画,并且单个View上存在多种动画效果,这时候就要用到AnimatorSet类了。AnimatorSet类用来实现复杂的组合动画,但功能上相比于AnimationSet强大多了。AnimatorSet针对ValueAnimator和ObjectAnimator都是适用的,但一般而言,基本不会用到ValueAnimator的组合动画。
在AnimatorSet中给为我们提供了两个方法playSequentially和playTogether,
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();
}
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只有上一个控件做完动画以后,才会激活下一个控件的动画,如果上一控件的动画是无限循环,那下一个控件就无法做动画了。
AnimatorSet.Builder用于实现playTogether和playSequentially无法实现的效果,可以实现非常自由的组合动画,比如有三个动画A,B,C想先播放C然后同时播放A和B,利用playTogether和playSequentially是没办法实现的,但利用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();
}
在AnimatorSet中也可以添加监听器,添加方法为:
public void addListener(AnimatorListener listener);
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);
}
方法 | 概述 |
---|---|
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设置了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();
}
XML标签 | java类 |
---|---|
ValueAnimator | |
ObjectAnimator | |
AnimatorSet |
- | - |
---|---|
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() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value=(float)animation.getAnimatedValue();
ivImage01.setScaleX(value);
ivImage01.setScaleY(value);
}
});
valueAnimator.start();
}
- | - |
---|---|
objectAnimator | 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();
}
字段意义及使用方法
- | - |
---|---|
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:虽然动画部分上个月就学习完了,但由于时间紧张,工作也比较忙,间隔一个月后才陆陆续续的总结完毕。),后续也会在博客中放一些动画例子。