当前位置: 首页 > 工具软件 > View Animator > 使用案例 >

Android Animator(动画)类 详解

霍建柏
2023-12-01

动画分为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标签程序代码
animatorValueAnimator
objectAnimatorObjectAnimator
setAnimatorSet

例:实现一个从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());

 类似资料: