1、插值器(Interpolator)
1.1、简介
- 定义:一个接口
- 作用: 设置属性值从初始值过滤到结束值的变化规律,即确定了动画的变化模式
例如:匀减速,匀加速,先减速后加速,先加速后减速,匀速等等。
1.2、应用举例
实现非线性运动的动画效果(动画的速率不是一成不变的,可能有加速、减速)
1.3、具体使用
插值器在动画中的设置方式有两种:Java 代码中设置和XML文件中设置
1、在XML中设置
2、在Java代码中设置
//1.创建透明动画对象
Animation animation = new AlphaAnimation(1, 0);
//2.创建插值器
Interpolator interpolator = new OvershootInterpolator();
//3.给动画设置插值器
animation.setInterpolator(interpolator);
//4.播放动画
ivOne.startAnimation(animation);
以上我们用到了OvershootInterpolator这个系统的插值 器,那其实系统内置9种插值器的实现,我们通过表格的形式列出来。
1.4、自定义插值器
以上我们介绍了插值器的如何使用以及系统内置的9中插值器,其实系统的插值器已经基本可以满足我们平常的开发使用。但是有时候我们需要做到的效果系统的插值器无法实现,我们也可以自定义插值器。
- 具体实现
自定义插值器需要实现 Interpolator / TimeInterpolator接口 & 复写getInterpolation()
(1)补间动画 实现 Interpolator接口;属性动画实现TimeInterpolator接口
(2)TimeInterpolator接口是属性动画中新增的,用于兼容Interpolator接口,这使得所有过去的Interpolator实现类都可以直接在属性动画使用 - 实例
自定义一个Interpolator,先减速后加速
1、创建MyInterpolator类,实现TimeInterpolator接口,最核心的部分就是通过改变getInterpolation返回值的变化来设置为先减速后加速。
package com.example.administrator.workmanager;
import android.animation.TimeInterpolator;
/**
* weishixiong
* 2019/4/23
*/
public class MyInterpolator implements TimeInterpolator {
@Override
public float getInterpolation(float input) {
float result;
//动画前半部分
if(input<=0.5){
result = (float) (Math.sin(Math.PI * input)) / 2;
// 使用正弦函数来实现先减速后加速的功能,逻辑如下:
// 因为正弦函数初始弧度变化值非常大,刚好和余弦函数是相反的
// 随着弧度的增加,正弦函数的变化值也会逐渐变小,这样也就实现了减速的效果。
// 当弧度大于π/2之后,整个过程相反了过来,现在正弦函数的弧度变化值非常小,
// 渐渐随着弧度继续增加,变化值越来越大,弧度到π时结束,这样从0过度到π,也就实现了先减速后加速的效果
}
else{
result = (float) (2 - Math.sin(Math.PI * input)) / 2;
}
return result;
}
}
2、给属性动画设置插值器,View执行属性动画
//获得当前图片的位置
float curTranslationX = ivOne.getTranslationX();
// 创建动画对象 & 设置动画
// 表示的是:
// 动画作用对象是ivOne
// 动画作用的对象的属性是X轴平移
// 动画效果是:从当前位置平移到 x=300 再平移到初始位置
ObjectAnimator animator = ObjectAnimator.ofFloat(ivOne, "translationX", curTranslationX, 300,curTranslationX);
animator.setDuration(5000);
// // 设置插值器
animator.setInterpolator(new MyInterpolator());
// 启动动画
animator.start();
以上我们就完成了一个自定义的插值器,并通过属性动画进行设置,然后执行动画。
2、估值器(TypeEvaluator)
2.1、简介
- 定义:一个接口
- 作用: 设置属性值从初始值过度到最终值的具体变化数值。
(1)插值器决定的是动画具体的变化规律
(2)估值器指的是在某个变化规律上具体的变化数值,比如动画的加速具体的数值。
2.2、应用场景
配合插值器完成非线性的动画效果
2.3、具体实现
ObjectAnimator anim = ObjectAnimator.ofObject(myView2, "height", new IntEvaluator(),1,3);
设置一个View的高从1变化到3的效果,在第4个参数中传入对应估值器类的对象,IntEvaluator指的是以整型的形式从初始值 - 结束值 进行过渡。
系统内置的估值器有3个:
- IntEvaluator:以整型的形式从初始值 - 结束值 进行过渡
- FloatEvaluator:以浮点型的形式从初始值 - 结束值 进行过渡
- ArgbEvaluator:以Argb类型的形式从初始值 - 结束值 进行过渡
2.4、自定义估值器
如果以上系统内置的估值器无法满足开发的需求,我们可以自定义估值器。
- 实例
自定义一个估值器,作用在一个圆上,通过改变圆心的坐标,来实现动画效果。
1、创建圆心实体类Point.java
package com.example.administrator.workmanager;
/**
* 圆心实体类
*/
public class Point {
// 设置两个变量用于记录坐标的位置
private float x;
private float y;
// 构造方法用于设置坐标
public Point(float x, float y) {
this.x = x;
this.y = y;
}
// get方法用于获取坐标
public float getX() {
return x;
}
public float getY() {
return y;
}
}
2、实现TypeEvaluator接口,自定义估值器
package com.example.administrator.workmanager;
import android.animation.TypeEvaluator;
// 实现TypeEvaluator接口
public class PointEvaluator implements TypeEvaluator {
/**
*
* @param fraction 插值器getInterpolation()的返回值 可以理解为动画进行进度的百分比。
* 当进度为100%的时候,即动画完成了
* @param startValue 动画的初始值
* @param endValue 动画的结束值
* @return
*/
@Override
public Object evaluate(float fraction, Object startValue, Object endValue) {
// 将动画初始值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;
}
}
3、将属性动画作用到自定义View当中
package com.example.administrator.workmanager;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
/**
* weishixiong
*/
public class MyView extends View {
// 设置需要用到的变量
public static final float RADIUS = 70f;// 圆的半径 = 70
private Point currentPoint;// 当前点坐标
private Paint mPaint;// 绘图画笔
// 构造方法(初始化画笔)
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
// 初始化画笔
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.BLUE);
}
// 复写onDraw()从而实现绘制逻辑
// 绘制逻辑:先在初始点画圆,通过监听当前坐标值(currentPoint)的变化,每次变化都调用onDraw()重新绘制圆,从而实现圆的平移动画效果
@Override
protected void onDraw(Canvas canvas) {
// 如果当前点坐标为空(即第一次)
if (currentPoint == null) {
currentPoint = new Point(RADIUS, RADIUS);
// 创建一个点对象(坐标是(70,70))
// 在该点画一个圆:圆心 = (70,70),半径 = 70
float x = currentPoint.getX();
float y = currentPoint.getY();
canvas.drawCircle(x, y, RADIUS, mPaint);
// (重点关注)将属性动画作用到View中
// 步骤1:创建初始动画时的对象点 & 结束动画时的对象点
Point startPoint = new Point(RADIUS, RADIUS);// 初始点为圆心(70,70)
Point endPoint = new Point(700, 1000);// 结束点为(700,1000)
// 步骤2:创建动画对象 & 设置初始值 和 结束值
ValueAnimator anim = ValueAnimator.ofObject(new PointEvaluator(), startPoint, endPoint);
// 参数说明
// 参数1:TypeEvaluator 类型参数 - 使用自定义的PointEvaluator(实现了TypeEvaluator接口)
// 参数2:初始动画的对象点
// 参数3:结束动画的对象点
// 步骤3:设置动画参数
anim.setDuration(5000);
// 设置动画时长
// 步骤3:通过 值 的更新监听器,将改变的对象手动赋值给当前对象
// 此处是将 改变后的坐标值对象 赋给 当前的坐标值对象
// 设置 值的更新监听器
// 即每当坐标值(Point对象)更新一次,该方法就会被调用一次
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
currentPoint = (Point) animation.getAnimatedValue();
// 将每次变化后的坐标值(估值器PointEvaluator中evaluate()返回的Piont对象值)到当前坐标值对象(currentPoint)
// 从而更新当前坐标值(currentPoint)
// 步骤4:每次赋值后就重新绘制,从而实现动画效果
invalidate();
// 调用invalidate()后,就会刷新View,即才能看到重新绘制的界面,即onDraw()会被重新调用一次
// 所以坐标值每改变一次,就会调用onDraw()一次
}
});
anim.start();
// 启动动画
} else {
// 如果坐标值不为0,则画圆
// 所以坐标值每改变一次,就会调用onDraw()一次,就会画一次圆,从而实现动画效果
// 在该点画一个圆:圆心 = (30,30),半径 = 30
float x = currentPoint.getX();
float y = currentPoint.getY();
canvas.drawCircle(x, y, RADIUS, mPaint);
}
}
}
4、在布局文件加入自定义View空间
已经我们就完成了一个圆,通过自定义估值器,改变圆心坐标,完成圆类似抛物线的效果。
3、小结
插值器和估值器主要是为了实现一些复杂效果而产生,插值器确定的是动画的变化规律,估值器确定的是动画变化的具体数值。系统中内置有了常用的插值器和估值器,假如在开发中系统内置的不能满足我们的需求,我们也可以自定义插值器和估值器。