集合动画AnimationSet
补间动画有四大类:透明度动画AlphaAnimation、旋转动画RotateAnimation、缩放动画ScaleAnimation、平移动画TranslateAnimation,而集合动画AnimationSet便是用来将几个补间动画组装起来。即在同一时刻,让某视图呈现出多种动画效果,如一边缩放一边旋转。
下面是AnimationSet的常用方法:
addAnimation : 添加动画。
setFillAfter : 设置是否维持结束画面。true表示动画结束后停留在结束画面,false表示动画结束后恢复到开始画面。
setRepeatMode : 设置重播模式。RESTART表示从头开始,REVERSE表示倒过来开始。
setDuration : 设置动画的持续时间。
setStartTime : 设置动画的开始时间。Animation.START_ON_FIRST_FRAME表示当前时间,其他值表示转换为整型数的时间。一般无需调用该方法,默认就是立即开始播放。
setInterpolator : 设置动画的插值器。
属性动画ObjectAnimator
视图View有许多属性,四种补间动画其实只用到了六个属性,分别是alpha、rotation、scaleX、scaleY、translationX、translationY,这六个属性对应View类的方法是setAlpha、setRotation、setScaleX、setScaleY、setTranslationX、setTranslationY。属性动画便是为了突破补间动画的局限,它让View所有的公开属性都能够实现动画效果,例如背景颜色、文字颜色等等,只要设定某属性的起始值与终止值,即可实现该属性的动画渐变。
下面是ObjectAnimator的常用方法:
ofInt : 定义整型属性的属性动画。
ofFloat : 定义浮点型属性的属性动画。
ofObject : 定义对象属性的属性动画。用于属性值不是整型与浮点型的,例如Rect对象。
setDuration : 设置动画的持续时间。
setInterpolator : 设置动画的插值器。
start : 开始播放动画。
属性动画组合AnimatorSet
AnimationSet用来组装补间动画,而用于组装属性动画的另有其人,它就是AnimatorSet。AnimatorSet组装属性动画是通过内部类Builder实现的,下面是AnimationSet.Builder的组装方法:
with : 与当前动画一起播放。
before : 在当前动画之前播放。
after : 在当前动画之后播放。
下面是AnimatorSet的常用方法:
setDuration : 设置动画的持续时间。
setInterpolator : 设置动画的插值器。
play : 设置初始动画,即当前动画。该方法返回AnimationSet.Builder对象,可对Builder对象添加新的属性动画,从而实现组装功能。
start : 开始播放动画。
pause : 暂停播放。
resume : 恢复播放。
cancel : 取消播放。
end : 结束播放。end方法与cancel方法的区别在于:cancel方法会触发AnimatorListener的onAnimationCancel事件,而end方法不会触发该事件。
isRunning : 判断动画是否在播放。
插值器和估值器
插值器
插值器用来控制属性变化的速率,也可以理解为动画播放的速度,默认是匀速播放。要设置一个插值器,调用setInterpolator方法即可,不管是补间动画、还是集合动画、还是属性动画、还是属性动画组合,都可以设置插值器。
下面是插值器具体实现类的说明:
LinearInterpolator : 匀速
AccelerateInterpolator : 加速
DecelerateInterpolator : 减速
AccelerateDecelerateInterpolator : 钟摆速度,即前半段加速、后半段减速
AnticipateInterpolator : 后退几步再往前冲
AnticipateOvershootInterpolator : 后退几步再往前冲,冲过头再归位
BounceInterpolator : 皮球落地(落地后会弹起几次)
CycleInterpolator : 以开始位置为中线而晃动(类似摇摆,开始位置与结束位置的距离就是摇摆的幅度)
OvershootInterpolator : 冲过头再归位
估值器
估值器专用于属性动画,主要是描述该属性的数值变化要采用什么单位,比如说整型数的渐变数值都要取整,颜色的渐变数值要按照RGB格式取整,矩形的渐变数值要同时对横坐标和纵坐标取整等等。要设置属性动画的估值器,调用ObjectAnimator的setEvaluator方法即可。
下面是估值器具体实现类的说明(如果属性类型是自定义的,那也得自定义对应的估值器):
IntEvaluator : 整型估值器
FloatEvaluator : 浮点型估值器
ArgbEvaluator : 颜色估值器
RectEvaluator : 矩形估值器
属性方法与估值器的对应关系
为方便记忆属性动画中属性方法与估值器的关系,下面列出相关对象的对应关系:
ofInt——IntEvaluator——颜色
ofInt——ArgbEvaluator——颜色,如backgroundColor、textColor等等
ofFloat——FloatEvaluator——大部分属性,如alpha、rotation、scaleY、translationX等等
ofObject——RectEvaluator——范围,如clipBounds
代码例子
下面是集合动画的代码示例
import com.example.exmanimation.util.MetricsUtil;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.AnimationSet;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.RotateAnimation;
import android.view.animation.ScaleAnimation;
import android.view.animation.TranslateAnimation;
import android.widget.Button;
import android.widget.ImageView;
public class SetActivity extends Activity implements OnClickListener, AnimationListener {
private final static String TAG = "SetActivity";
private ImageView iv_set;
private Animation translateAnimation, alphaAnimation, scaleAnimation, rotateAnimation;
private AnimationSet setAnimation;
private Animation translateAnimation9;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_set);
Button btn_set_start = (Button) findViewById(R.id.btn_set_start);
Button btn_translate_start = (Button) findViewById(R.id.btn_translate_start);
btn_set_start.setOnClickListener(this);
btn_translate_start.setOnClickListener(this);
iv_set = (ImageView) findViewById(R.id.iv_set);
translateAnimation = new TranslateAnimation(0.1f, 0.1f, 0.1f,
MetricsUtil.dip2px(this, 250));
translateAnimation.setDuration(3000);
translateAnimation.setFillAfter(true);
translateAnimation.setInterpolator(new AccelerateInterpolator());
alphaAnimation = new AlphaAnimation(1.0f, 0.1f);
alphaAnimation.setDuration(3000);
alphaAnimation.setFillAfter(true);
scaleAnimation = new ScaleAnimation(1.0f, 0.1f, 1.0f, 1.0f);
scaleAnimation.setDuration(3000);
scaleAnimation.setFillAfter(true);
rotateAnimation = new RotateAnimation(0f, 360f,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
0.5f);
rotateAnimation.setDuration(3000);
rotateAnimation.setFillAfter(true);
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.btn_translate_start) {
translateAnimation9 = new TranslateAnimation(0.1f, 0.1f, 0.1f,
MetricsUtil.dip2px(this, 250));
translateAnimation9.setDuration(3000);
translateAnimation9.setFillAfter(true);
translateAnimation9.setInterpolator(new AccelerateInterpolator());
iv_set.startAnimation(translateAnimation9);
translateAnimation9.setAnimationListener(this);
} else if (v.getId() == R.id.btn_set_start) {
setAnimation = new AnimationSet(true);
setAnimation.addAnimation(translateAnimation);
setAnimation.addAnimation(alphaAnimation);
setAnimation.addAnimation(scaleAnimation);
setAnimation.addAnimation(rotateAnimation);
setAnimation.setFillAfter(true);
iv_set.startAnimation(setAnimation);
setAnimation.setAnimationListener(this);
}
}
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
Animation translateAnimation2 = new TranslateAnimation(0.1f, 0.1f, MetricsUtil.dip2px(this, 250), 0.1f);
translateAnimation2.setDuration(3000);
translateAnimation2.setFillAfter(true);
Animation alphaAnimation2 = new AlphaAnimation(0.1f, 1.0f);
alphaAnimation2.setDuration(3000);
alphaAnimation2.setFillAfter(true);
Animation scaleAnimation2 = new ScaleAnimation(0.1f, 1.0f, 1.0f, 1.0f);
scaleAnimation2.setDuration(3000);
scaleAnimation2.setFillAfter(true);
Animation rotateAnimation2 = new RotateAnimation(0f, -360f,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
rotateAnimation2.setDuration(3000);
rotateAnimation2.setFillAfter(true);
if (animation.equals(translateAnimation9)) {
Animation translateAnimation10 = new TranslateAnimation(0.1f, 0.1f, MetricsUtil.dip2px(this, 250), 0.1f);
translateAnimation10.setDuration(3000);
translateAnimation10.setFillAfter(true);
translateAnimation10.setInterpolator(new DecelerateInterpolator());
iv_set.startAnimation(translateAnimation10);
} else if (animation.equals(setAnimation)) {
AnimationSet setAnimation2 = new AnimationSet(true);
setAnimation2.addAnimation(translateAnimation2);
setAnimation2.addAnimation(alphaAnimation2);
setAnimation2.addAnimation(scaleAnimation2);
setAnimation2.addAnimation(rotateAnimation2);
setAnimation2.setFillAfter(true);
iv_set.startAnimation(setAnimation2);
}
}
@Override
public void onAnimationRepeat(Animation animation) {
}
}
下面是属性动画及属性动画组合的代码示例
import com.example.exmanimation.util.MetricsUtil;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.AnimationSet;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.RotateAnimation;
import android.view.animation.ScaleAnimation;
import android.view.animation.TranslateAnimation;
import android.widget.Button;
import android.widget.ImageView;
public class SetActivity extends Activity implements OnClickListener, AnimationListener {
private final static String TAG = "SetActivity";
private ImageView iv_set;
private Animation translateAnimation, alphaAnimation, scaleAnimation, rotateAnimation;
private AnimationSet setAnimation;
private Animation translateAnimation9;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_set);
Button btn_set_start = (Button) findViewById(R.id.btn_set_start);
Button btn_translate_start = (Button) findViewById(R.id.btn_translate_start);
btn_set_start.setOnClickListener(this);
btn_translate_start.setOnClickListener(this);
iv_set = (ImageView) findViewById(R.id.iv_set);
translateAnimation = new TranslateAnimation(0.1f, 0.1f, 0.1f,
MetricsUtil.dip2px(this, 250));
translateAnimation.setDuration(3000);
translateAnimation.setFillAfter(true);
translateAnimation.setInterpolator(new AccelerateInterpolator());
alphaAnimation = new AlphaAnimation(1.0f, 0.1f);
alphaAnimation.setDuration(3000);
alphaAnimation.setFillAfter(true);
scaleAnimation = new ScaleAnimation(1.0f, 0.1f, 1.0f, 1.0f);
scaleAnimation.setDuration(3000);
scaleAnimation.setFillAfter(true);
rotateAnimation = new RotateAnimation(0f, 360f,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
0.5f);
rotateAnimation.setDuration(3000);
rotateAnimation.setFillAfter(true);
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.btn_translate_start) {
translateAnimation9 = new TranslateAnimation(0.1f, 0.1f, 0.1f,
MetricsUtil.dip2px(this, 250));
translateAnimation9.setDuration(3000);
translateAnimation9.setFillAfter(true);
translateAnimation9.setInterpolator(new AccelerateInterpolator());
iv_set.startAnimation(translateAnimation9);
translateAnimation9.setAnimationListener(this);
} else if (v.getId() == R.id.btn_set_start) {
setAnimation = new AnimationSet(true);
setAnimation.addAnimation(translateAnimation);
setAnimation.addAnimation(alphaAnimation);
setAnimation.addAnimation(scaleAnimation);
setAnimation.addAnimation(rotateAnimation);
setAnimation.setFillAfter(true);
iv_set.startAnimation(setAnimation);
setAnimation.setAnimationListener(this);
}
}
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
Animation translateAnimation2 = new TranslateAnimation(0.1f, 0.1f, MetricsUtil.dip2px(this, 250), 0.1f);
translateAnimation2.setDuration(3000);
translateAnimation2.setFillAfter(true);
Animation alphaAnimation2 = new AlphaAnimation(0.1f, 1.0f);
alphaAnimation2.setDuration(3000);
alphaAnimation2.setFillAfter(true);
Animation scaleAnimation2 = new ScaleAnimation(0.1f, 1.0f, 1.0f, 1.0f);
scaleAnimation2.setDuration(3000);
scaleAnimation2.setFillAfter(true);
Animation rotateAnimation2 = new RotateAnimation(0f, -360f,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
rotateAnimation2.setDuration(3000);
rotateAnimation2.setFillAfter(true);
if (animation.equals(translateAnimation9)) {
Animation translateAnimation10 = new TranslateAnimation(0.1f, 0.1f, MetricsUtil.dip2px(this, 250), 0.1f);
translateAnimation10.setDuration(3000);
translateAnimation10.setFillAfter(true);
translateAnimation10.setInterpolator(new DecelerateInterpolator());
iv_set.startAnimation(translateAnimation10);
} else if (animation.equals(setAnimation)) {
AnimationSet setAnimation2 = new AnimationSet(true);
setAnimation2.addAnimation(translateAnimation2);
setAnimation2.addAnimation(alphaAnimation2);
setAnimation2.addAnimation(scaleAnimation2);
setAnimation2.addAnimation(rotateAnimation2);
setAnimation2.setFillAfter(true);
iv_set.startAnimation(setAnimation2);
}
}
@Override
public void onAnimationRepeat(Animation animation) {
}
}
点击下载本文用到的集合动画与属性动画的工程代码
点此查看Android开发笔记的完整目录