一、概述
本篇文章续接Android属性动画(一),介绍属性动画中非常重要的两个部分:插值器(Interpolator)和估值器(TypeEvaluator)。它们在属性动画中分别用于动画随时间流逝的变化规律和定义从初始值过渡到结束值的计算规则,本文结构如下:
- 插值器(Interpolator)的介绍和使用
- 估值器(TypeEvaluator)的介绍和使用
二、插值器Interpolator
插值器(Interpolator)用于定义动画随时间流逝的变化规律。这句话说起来比较抽象,但其实在我们实际使用属性动画的时候,我们能明显感觉到插值器的作用。
例如默认采用的加减速插值器,它会在动画开始执行逐渐加速,然后又逐渐减速直至动画结束;而线性插值器则是按着一个均匀的速度执行完整个动画的。它们随着动画执行比例的变化规律如下图所示:
图中线上某点所在的斜率即为在某时刻的速率。从图上也可以明显看到加减速插值器先逐渐加速、再逐渐减速,而线性插值器一直保持恒定的速率执行完成。在知道了插值器的作用之后,接下来我们就来看Android中有哪些内置的插值器。
1. 系统内置的插值器
Android系统中共内置了9种插值器,如下表所示:
插值器名称 | 作用 |
---|---|
AccelerateDecelerateInterpolator | 加减速插值器,动画先加速,后减速 |
LinearInterpolator | 线性插值器,动画匀速运行 |
AccelerateInterpolator | 加速插值器,动画加速运行至结束 |
DecelerateInterpolator | 减速插值器,动画减速运行至结束 |
OvershootInterpolator | 快速完成动画,超出终点一小部分后再回到终点 |
AnticipateInterpolator | 先后退一小步再加速前进至结束 |
AnticipateOvershootInterpolator | 先后退一小步再加速前进,超出终点一小部分后再回到终点 |
BounceInterpolator | 弹性插值器,在动画结束之前会有一个弹性动画的效果 |
CycleInterpolator | 周期运动 |
文字说明比较抽象,笔者下面通过图像的形式来展示这些插值器随时间流逝的变化效果:
接下来我们就来看到插值器的相关接口以及如何自定义一个插值器。
2. TimeInterpolator接口
自定义插值器我们需要实现 Interpolator
/ TimeInterpolator
接口并实现接口方法getInterpolation
。属性动画实现的是TimeInterpolator
接口,而补间动画实现的则是Interceptor
接口。事实上Interpolator
接口继承了TimeInterceptor
接口,这样做是基于兼容性的考虑,使得过去所有应用于补间动画的插值器都可以直接应用在属性动画上。为了我们的自定义插值器具有更好的兼容性,推荐实现Interpolator
接口。
接下来看到TimeInterpolator
接口的定义:
/**
* A time interpolator defines the rate of change of an animation. This allows animations
* to have non-linear motion, such as acceleration and deceleration.
*/
public interface TimeInterpolator {
/**
* Maps a value representing the elapsed fraction of an animation to a value that represents
* the interpolated fraction. This interpolated value is then multiplied by the change in
* value of an animation to derive the animated value at the current elapsed animation time.
*
* @param input A value between 0 and 1.0 indicating our current point
* in the animation where 0 represents the start and 1.0 represents
* the end
* @return The interpolation value. This value can be more than 1.0 for
* interpolators which overshoot their targets, or less than 0 for
* interpolators that undershoot their targets.
*/
float getInterpolation(float input);
}
可以看到这个接口只有一个接口方法getInterpolation
方法需要实现,它是用于定义动画随时间流逝的变化规律的,它的参数input
表示的是当前动画执行比例,如0.5表示动画现在执行了50%。返回值表示动画的完成度,在属性动画中称之为fraction
。
我们通过系统内置的几个插值器类来看看如何使用这个方法,先看到LinearInterpolator
:
public class LinearInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {
public LinearInterpolator() {
}
public LinearInterpolator(Context context, AttributeSet attrs) {
}
public float getInterpolation(float input) {
return input;
}
......
}
可以看到LinearInterpolator
继承自BaseInterpolator
,这是一个抽象类,它实现了Interpolator
接口。所以LinearInterpolator
相当于间接实现了Interpolator
接口,接下来看到getInterpolation
的实现:
public float getInterpolation(float input) {
return input