Android Animator动画类 详解

  • 动画分为3种
  • ValueAnimator类
  • ObjectAnimator类
  • AnimatorSet类
  • Animator的addListener()方法(监听器)
  • 适配器AnimatorListenerAdapter
  • 使用XML编写动画
  • TimeInterpolator(时间补间器)接口
  • ViewPropertyAnimator的用法


动画分为3种

  1. 逐帧动画(frame-by-frame animation) 类似于动画片的工作原理
  2. 补间动画(tweened animation) 对View进行一系列的动画操作,包括淡入淡出、缩放、平移、旋转四种;补间动画是只能够作用在View上
  3. 属性动画(property animation) 一种不断地对值进行操作,并将值赋值到指定对象的指定属性上,是任意对象的任意属性

ValueAnimator类

      对值进行了一个平滑的动画过渡;我们只需要将初始值和结束值提供给ValueAnimator,并且告诉它动画所需运行的时长,那么ValueAnimator就会自动帮我们完成从初始值平滑地过渡到结束值这样的效果

方法

使用

ofFloat(float… values)

构建ValueAnimator的实例,方法当中允许传入多个float类型的参数

例:将一个值从0平滑过渡到1或 从0过渡到5,再过渡到3,再过渡到10

ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);

ValueAnimator anim = ValueAnimator.ofFloat(0f, 5f, 3f, 10f);

ofInt(int… values)

构建ValueAnimator的实例,方法当中允许传入多个Int类型的参数

例:将一个值从0平滑过渡到1或 从0过渡到5,再过渡到3,再过渡到10

ValueAnimator anim = ValueAnimator.ofInt(0, 1);

ValueAnimator anim = ValueAnimator.ofInt(0, 5, 3, 10);

ofObject(TypeEvaluator evaluator, Object… values)

构建ValueAnimator的实例,用于对任意对象进行动画操作

evaluator:数值具体变化过程的当前数值,是一个自定义的 Evaluator

values:指定动画变化区间,类比参考ofInt()、ofFloat()

例:

1. 先定义个Point类

public class Point {

      private float x;

      private float y;

      public Point(float x, float y){

            this.x = x;

            this.y = y;

      }

      public float getX() {

            return x;

      }

      public float getY(){

            return y;

      }

}

2. 再定义PointEvaluator 类实现TypeEvaluator的接口再使用

public class PointEvaluator implements TypeEvaluator {

      @Override

      public Character evaluate(float fraction, Character startValue, Character endValue) {

            //将startValue和endValue强转成Point对象

            Point start = (Point) startValue;

            Point end = (Point) endValue;

            //当前值 = 初始值 + fraction * (结束值 - 初始值)

            float x = start.getX() + fraction * (end.getX() - start.getX());

            float y = start.getY() + fraction * (end.getY() - start.getY());

            //组装一个新的Point对象当中并返回

            Point point = new Point(x,y);

            return point;

       }

}

3. 使用

Point point1 = new Point(0, 0);

Point point2 = new Point(300, 300);

ValueAnimator anim = ValueAnimator.ofObject(new PointEvaluator(), point1, point2);

setDuration()

设置动画运行的时长,单位毫秒

例:设置动画时长600毫秒

anim.setDuration(600);

start()

启动动画

例:anim.start();

setStartDelay()

设置动画延迟播放的时间,单位毫秒

setRepeatCount()

设置动画循环播放的次数

setRepeatMode()

设置动画循环播放的模式

2种模式如下:

1.RESTART重新播放

2.REVERSE倒序播放

ValueAnimator类工作流程如下
ofInt(0, 100)--------------------------->加速器--------------------------->Evaluator--------------------------->监听器返回
动画运行的值区间                当前值区间的值              计算当前进度的数值                 在AnimatorUpdateListener中返回

ObjectAnimator类

      可以对任意对象的任意属性进行动画操作;ObjectAnimator类是继承自ValueAnimator的,底层的动画实现机制也是基于ValueAnimator来完成的.ObjectAnimator内部的工作机制并不是直接对我们传入的属性名进行操作的,而是会去寻找这个属性名对应的get和set方法
构造方法如下:
public static ObjectAnimator ofFloat(Object target, String propertyName, float… values)
public static ObjectAnimator ofInt(Object target, String propertyName, float… values)
target: 指定执行动画的控件
propertyName: 指定控件的属性
values: 可变长参数
例:

//透明度动画
ObjectAnimator animator = ObjectAnimator.ofFloat(view,"alpha",1,0,1);  
animator.setDuration(2000);  
animator.start(); 

//旋转动画:围绕x轴旋转
ObjectAnimator animator = ObjectAnimator.ofFloat(tv,"rotationX",0,270,0);  
animator.setDuration(2000);  
animator.start();

//旋转动画:围绕y轴旋转
ObjectAnimator animator = ObjectAnimator.ofFloat(tv,"rotationY",0,180,0);  
animator.setDuration(2000);  
animator.start();

//旋转动画:围绕z轴旋转
ObjectAnimator animator = ObjectAnimator.ofFloat(tv,"rotation",0,270,0);  
animator.setDuration(2000);  
animator.start();  

//平移动画:在x轴上平移
ObjectAnimator animator = ObjectAnimator.ofFloat(tv, "translationX", 0, 200, -200,0);  
animator.setDuration(2000);  
animator.start(); 

//平移动画:在y轴上平移
ObjectAnimator animator = ObjectAnimator.ofFloat(tv, "translationY", 0, 200, -100,0);  
animator.setDuration(2000);  
animator.start(); 

//缩放动画:在x轴缩放
ObjectAnimator animator = ObjectAnimator.ofFloat(tv, "scaleX", 0, 3, 1);  
animator.setDuration(2000);  
animator.start();

//缩放动画:在y轴上缩放
ObjectAnimator animator = ObjectAnimator.ofFloat(tv, "scaleY", 0, 3, 1);  
animator.setDuration(2000);  
animator.start();

ObjectAnimator类工作流程如下
ofFloat(tv, “scaleX”, 0, 3, 1)--------------------------->加速器--------------------------->Evaluator--------------------------->调用set函数
定义动画对象和区间                当前值区间的值              计算当前进度的数值                 使用set函数完成动画

AnimatorSet类

      实现组合动画功能

方法

使用

play(Animator anim)

返回一个AnimatorSet.Builder的实例能够控制动画的执行顺序和相互之间的依赖。

例:

同下

after(Animator anim)

将现有动画插入到传入的动画之后执行

例:

ObjectAnimator objectAnimator1 = ObjectAnimator.ofArgb(mTextView, “backgroundColor”, Color.WHITE, Color.GREEN);

ObjectAnimator objectAnimator2 = ObjectAnimator.ofFloat(mTextView, “scaleX”, 0.1f, 1.2f);

ObjectAnimator objectAnimator3 = ObjectAnimator.ofFloat(mTextView, “scaleY”, 0.5f, 1.0f);

AnimatorSet animatorSet = new AnimatorSet();

animatorSet.play(objectAnimator1).after(objectAnimator2);

animatorSet.setDuration(3000);

animatorSet.start();

after(long delay)

将现有动画延迟指定毫秒后执行

例:

ObjectAnimator objectAnimator1 = ObjectAnimator.ofArgb(mTextView, “backgroundColor”, Color.WHITE, Color.GREEN);

ObjectAnimator objectAnimator2 = ObjectAnimator.ofFloat(mTextView, “scaleX”, 0.1f, 1.2f);

ObjectAnimator objectAnimator3 = ObjectAnimator.ofFloat(mTextView, “scaleY”, 0.5f, 1.0f);

AnimatorSet animatorSet = new AnimatorSet();

animatorSet.play(objectAnimator1).after(objectAnimator2).after(10000);

animatorSet.setDuration(3000);

animatorSet.start();

before(Animator anim)

将现有动画插入到传入的动画之前执行

例:

ObjectAnimator objectAnimator1 = ObjectAnimator.ofArgb(mTextView, “backgroundColor”, Color.WHITE, Color.GREEN);

ObjectAnimator objectAnimator2 = ObjectAnimator.ofFloat(mTextView, “scaleX”, 0.1f, 1.2f);

ObjectAnimator objectAnimator3 = ObjectAnimator.ofFloat(mTextView, “scaleY”, 0.5f, 1.0f);

AnimatorSet animatorSet = new AnimatorSet();

animatorSet.play(objectAnimator1).before(objectAnimator2);

animatorSet.setDuration(3000);

animatorSet.start();

with(Animator anim)

将现有动画和传入的动画同时执行

例:

ObjectAnimator objectAnimator1 = ObjectAnimator.ofArgb(mTextView, “backgroundColor”, Color.WHITE, Color.GREEN);

ObjectAnimator objectAnimator2 = ObjectAnimator.ofFloat(mTextView, “scaleX”, 0.1f, 1.2f);

ObjectAnimator objectAnimator3 = ObjectAnimator.ofFloat(mTextView, “scaleY”, 0.5f, 1.0f);

AnimatorSet animatorSet = new AnimatorSet();

animatorSet.play(objectAnimator1).with(objectAnimator7).with(objectAnimator11);

animatorSet.setDuration(3000);

animatorSet.start();

Animator的addListener()方法(监听器)

      Animator类当中提供了一个addListener()方法,这个方法接收一个AnimatorListener,我们只需要去实现这个AnimatorListener就可以监听动画的各种事件了。ObjectAnimator是继承自ValueAnimator的,而ValueAnimator又是继承自Animator的,AnimatorSet也是继承自Animator的;因此都是可以使用addListener()这个方法的
例:添加一个监听器的代码如下所示:

anim.addListener(new AnimatorListener() {
	@Override
// onAnimationStart()方法会在动画开始的时候调用
	public void onAnimationStart(Animator animation) {
	}

	@Override
// onAnimationRepeat()方法会在动画重复执行的时候调用
	public void onAnimationRepeat(Animator animation) {
	}

	@Override
// onAnimationEnd()方法会在动画结束的时候调用
	public void onAnimationEnd(Animator animation) {
	}

	@Override
// onAnimationCancel()方法会在动画被取消的时候调用
	public void onAnimationCancel(Animator animation) {
	}
});

适配器AnimatorListenerAdapter

      使用这个类就可以解决掉实现接口繁琐的问题了;向addListener()方法中传入这个适配器对象,由于AnimatorListenerAdapter中已经将每个接口都实现好了,所以只需要单独重写这一个方法就可以了
例:

anim.addListener(new AnimatorListenerAdapter() {
	@Override
	public void onAnimationEnd(Animator animation) {
	}
}

使用XML编写动画

      通过XML来编写动画可能会比通过代码来编写动画要慢一些,但是在重用方面将会变得非常轻松,比如某个将通用的动画编写到XML里面,我们就可以在各个界面当中轻松去重用它。具体做法是在res目录下面新建一个animator文件夹,所有属性动画的XML文件都应该存放在这个文件夹当中

                                                                        XML标签与代码的对照表:

XML标签

程序代码

animator

ValueAnimator

objectAnimator

ObjectAnimator

set

AnimatorSet

例:实现一个从0到100平滑过渡的动画,在XML当中就可以这样写:

<animator xmlns:android="http://schemas.android.com/apk/res/android"
    android:valueFrom="0"
    android:valueTo="100"
    android:valueType="intType"/>

例:如果我们想将一个视图的alpha属性从1变成0,就可以这样写:

<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:valueFrom="1"
    android:valueTo="0"
    android:valueType="floatType"
    android:propertyName="alpha"/>

例:将一个视图先从屏幕外移动进屏幕,然后开始旋转360度,旋转的同时进行淡入淡出操作,就可以这样写:

<set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="sequentially" >
    <objectAnimator
        android:duration="2000"
        android:propertyName="translationX"
        android:valueFrom="-500"
        android:valueTo="0"
        android:valueType="floatType" >
    </objectAnimator>
    <set android:ordering="together" >
        <objectAnimator
            android:duration="3000"
            android:propertyName="rotation"
            android:valueFrom="0"
            android:valueTo="360"
            android:valueType="floatType" >
        </objectAnimator>
        <set android:ordering="sequentially" >
            <objectAnimator
                android:duration="1500"
                android:propertyName="alpha"
                android:valueFrom="1"
                android:valueTo="0"
                android:valueType="floatType" >
            </objectAnimator>
            <objectAnimator
                android:duration="1500"
                android:propertyName="alpha"
                android:valueFrom="0"
                android:valueTo="1"
                android:valueType="floatType" >
            </objectAnimator>
        </set>
    </set>
</set>

加载XML动画
1. 调用AnimatorInflater的loadAnimator将XML动画文件加载
2. 调用setTarget()方法将这个动画设置到某一个对象上
3. 调用start()方法启动动画
例:

Animator animator = AnimatorInflater.loadAnimator(context, R.animator.anim_file);
animator.setTarget(view);
animator.start();

TimeInterpolator(时间补间器)接口

自带TimeInterpolator
      TimeInterpolator接口已经有非常多的实现类了,这些都是Android系统内置好的并且我们可以直接使用的Interpolator。每个Interpolator都有它各自的实现效果

取值

说明

AccelerateDecelerateInterpolator

先加速后减速效果的Interpolator(默认)

AccelerateInterpolator

加速运动效果的Interpolator

AnticipateInterpolator

预计效果的Interpolator

AnticipateOvershootInterpolator

预测过度的Interpolator

BounceInterpolator

反弹效果的Interpolator

CycleInterpolator

循环效果的Interpolator

DecelerateInterpolator

减速运动效果的Interpolator

LinearInterpolator

线性效果的Interpolator

OvershootInterpolator

过度效果的Interpolator

PathInterpolator

路径效果的Interpolator

系统中TimeInterpolator的接口定义如下:

public interface TimeInterpolator {
      float getInterpolation(float input);
}

自定义TimeInterpolator
getInterpolation()方法中接收一个input参数,这个参数的值会随着动画的运行而不断变化,不过它的变化是非常有规律的,就是根据设定的动画时长匀速增加,变化范围是0到1。也就是说当动画一开始的时候input的值是0,到动画结束的时候input的值是1,而中间的值则是随着动画运行的时长在0到1之间变化的。input的值决定了fraction的值。input的值是由系统经过计算后传入到getInterpolation()方法中的,然后我们可以自己实现getInterpolation()方法中的算法,根据input的值来计算出一个返回值,而这个返回值就是fraction

例:自定义TimeInterpolator的使用

public class PointEvaluator implements TypeEvaluator {  // 实现TypeEvaluator接口
    @Override
    public Object evaluate(float fraction, Object startValue, Object endValue) {  //重写了evaluate()方法
        //将startValue和endValue强转成Point对象
        Point startPoint = (Point) startValue;   
        Point endPoint = (Point) endValue;
//根据fraction来计算当前动画的x和y的值
        float x = startPoint.getX() + fraction * (endPoint.getX() - startPoint.getX());
        float y = startPoint.getY() + fraction * (endPoint.getY() - startPoint.getY());
        //组装到一个新的Point对象当中并返回
        Point point = new Point(x, y);
        return point;
    }
}
public class DecelerateAccelerateInterpolator implements TimeInterpolator{  //实现TimeInterpolator接口
    @Override
    public float getInterpolation(float input) {  //getInterpolation()方法中的逻辑算法实现
        float result;
        if (input <= 0.5) {
            result = (float) (Math.sin(Math.PI * input)) / 2;
        } else {
            result = (float) (2 - Math.sin(Math.PI * input)) / 2;
        }
        return result;
    }
}

代码中使用

private void startAnimation() {
    Point startPoint = new Point(getWidth() / 2, RADIUS);
    Point endPoint = new Point(getWidth() / 2, getHeight() - RADIUS);
    ValueAnimator anim = ValueAnimator.ofObject(new PointEvaluator(), startPoint, endPoint);
    anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            currentPoint = (Point) animation.getAnimatedValue();
            invalidate();
        }
    });
    anim.setInterpolator(new DecelerateAccelerateInterpolator());  //使用定义的DecelerateAccelerateInterpolator类
    anim.setDuration(3000);
    anim.start();
}

ViewPropertyAnimator的用法

      TimeInterpolator为View的动画操作提供一种更加便捷的人性化用法,便于更加容易理解
animate()方法:是在Android 3.1系统上新增的一个方法,这个方法的返回值是一个ViewPropertyAnimator对象,也就是说拿到
                        这个对象之后我们就可以调用它的各种方法来实现动画效果了;ViewPropertyAnimator是支持连缀用法的,将所
                        有想要组合的动画通过这种连缀的式拼接起来,这样全部动画就都会一起被执行;
                        等到所有在ViewPropertyAnimator上设置的方法都执行完毕后,动画就会自动启动。当然如果不想使用这一默认
                        机制的话,我们也可以显式地调用start()方法来启动动画
例:TextView从常规状态变成透明状态

textview.animate().alpha(0f);
 //之前是这样的
 // ObjectAnimator animator = ObjectAnimator.ofFloat(textview, “alpha”, 0f);
 //animator.start(); 
 例:textview运动到500,500这个坐标点上
 textview.animate().x(500).y(500);
 例:textview运动到500,500这个坐标点上,运行5秒钟
 textview.animate().x(500).y(500).setDuration(5000);
 例:textview运动到500,500这个坐标点上,运行5秒钟并使用补间器
 textview.animate().x(500).y(500).setDuration(5000).setInterpolator(new BounceInterpolator());