文章目录
一、插值器(Interpolator)介绍
插值器是帮助定义动画变化率的接口,即加速动画、减速动画、重复动画等。
在上一章我们了解到补间动画有一个设置插值器的方法:anim.setInterpolator(Interpolator i)
Interpolator是一个接口,那么我们翻翻他有多少个实现:
二、实现
我们可以看到系统已经存在很多个可以直接使用的插值器,我们随便挑一个来使用,使用的方法非常的简单:
- 挑一个幸运插值器(OvershootInterpolator)
- 调用
anim.setInterpolator(OvershootInterpolator())
,直接new一个就行了。
可以发现动画会先是超过了原本“最终帧”的位置,然后又慢慢的回弹。
三、示例
我从网上找到几张图,可以提供参考:
四、自定义插值器
官方提供的插值器基本都会满足我们的需求,但是如果你怎样都觉得不满意,这个动画就是看着不爽!怎么办?那就只能去自定义一个插值器,来满足自己的需求(另外你还需要恨自信你的数学)。
1、 既然要自定义插值器,那么我们就创建一个类来继承 Interpolator接口:
class MyInterpolator : Interpolator {
override fun getInterpolation(input: Float): Float {
}
}
因为是个接口,所以必须实现其方法,好在只有一个方法需要改造。
万事开头难啊!
2、我们只能先参考官方是怎么实现的,挑一个幸运插值器(LinearInterpolator)来研究以下:
public float getInterpolation(float input) {
return input;
}
很简单,你给啥我返回啥~
3、赶紧查看官网作何解释吧!
- 有两个关键的值:给我们的input 和 输出给别人用的返回值。两个都是float类型的。
- input取值范围为[0,1],当值为0代表动画要开始了,当值为1代表动画结束了。
- 返回值可以是小于0,也可以大于1,越值了表示动画也会越过去,就像我们之前OvershootInterpolator的示例一样。
- 这个方法将表示动画经过部分的值映射到表示插值部分的值。然后将该插值乘以动画值的变化,以在当前经过的动画时间导出动画值。
前面三点我相信你们都看懂,最后一点肯定是一脸懵逼的~
没关系!我们结合LinearInterpolator就不难猜出,真正反映动画播放效果的就是我们要返回的值!
4、Demo
为此,我们来模仿以下LinearInterpolator做个简单的小例子:
override fun getInterpolation(input: Float): Float {
if (input>0.8){
return (input+0.2).toFloat();
}
return input
}
- 当动画播放到4/5之前,我们直接返回input,表示直线运行。
- 当动画播放到4/5之后,我们返回input+0.2,看看他会怎样。
我们发现,前面还好好的,匀速播放,等接近尾声的时候,突然跳动了!
5、小结
经过上面的分析,不难发现,插值器的关键之处,就在于如何操作
fun(input):Float 值,再返回其结果,就是动画最终的实现效果。
还记得我们之前说过,你还需要很自信你的数学,这是怎么个说法呢?我们直接看看官方其他的实现,你就明白了!
//OvershootInterpolator
private final float mTension;
public OvershootInterpolator() {
mTension = 2.0f;
}
public OvershootInterpolator(float tension) {
mTension = tension;
}
public float getInterpolation(float t) {
// _o(t) = t * t * ((tension + 1) * t + tension)
// o(t) = _o(t - 1) + 1
t -= 1.0f;
return t * t * ((mTension + 1) * t + mTension) + 1.0f;
}
//AccelerateInterpolator
private final float mFactor;
private final double mDoubleFactor;
public AccelerateInterpolator() {
mFactor = 1.0f;
mDoubleFactor = 2.0;
}
public AccelerateInterpolator(float factor) {
mFactor = factor;
mDoubleFactor = 2 * mFactor;
}
public float getInterpolation(float input) {
if (mFactor == 1.0f) {
return input * input;
} else {
return (float)Math.pow(input, mDoubleFactor);
}
}
看见了吧,没有好的数学功底,你别瞎参活了~