Android开发笔记(九十六)集合动画与属性动画

集合动画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开发笔记的完整目录

你可能感兴趣的:(android开发,Android开发笔记)