原文来自于:Android Animations Tutorial 5: More on Interpolators
译者注:这篇文章是一系列动画教程中的一篇,对Android内置的几种Interpolator(插值器)讲解得非常清楚,特作翻译,其他几篇文章有空也可以考虑翻译。这一系列的文章依次是:
Android Animations Tutorial 1: Introduction
Android Animations Tutorial 2: View Animations Overview
Android Animations Tutorial 3: Customising Animations
Android Animations Tutorial 4: Programming View Animations
Android Animations Tutorial 5: More on Interpolators
Android Animations Tutorial 6: Animation Sets and Start Offset
Android Animations Tutorial 7: The secret of fillBefore, fillAfter and fillEnabled
在动手实现自定义Interpolator之前,我们需要明白其背后的原理和概念。动画的基本原理是从开始时间到结束时间一帧一帧地播放静态图像,如果我们用0.0表示动画的开始时间点,用1.0表示动画的结束时间点,则动画时间轴上的每个点都可以转换成0.0到1.0之间的一个浮点数,本文中我们称为Time Index。比如,动画中间的时间点可以用0.5来表示。对于使用了LinearInterpolator(线性插值器)的平移动画来讲,在0.3这个时间点视图则刚好移动了整个动画的30%。
我们一般不会将Time Index直接带入到动画计算公式,这也是Interpolator的存在的意义。
从本质上来讲,Interpolator是一种数学函数,参数是0.0到1.0之间的浮点数,输出也是一个浮点数。如上图所示,这是一个AccelerateInterpolator(加速插值器)的图。目标对象的起始速度是0,然后逐渐增大(译者注:曲线的斜率是速度)。默认情况下,可以用下面的表达式来表示:
y = t^2
这里的y就是Interpolator的输出,t是Time Index。我们可以增加一个参数来对AccelerateInterpolator的行为进行自定义:
y = t ^(2f)
这里的f越大,起始速度越慢,但是后期加速度会更大;如果f=0.5,则和LinearInterpolator的行为一模一样了。
很多Interpolator都可以通过XML或者编程的方式来设置参数。通过XML方式需要在res/anim文件夹里面创建一个XML文件。比如,你想将AccelerateInterpolator的f参数设置为2,你可以创建这样一个文件
res/anim/my_accelerate_interpolator.xml,其内容如下:
<?xml version="1.0" encoding="utf-8"?> <accelerateInterpolator xmlns:android="http://schemas.android.com/apk/res/android" android:factor="2" />
注意,accelerateInterpolator表示这是一个AccelerateInterpolator,第一个字符小写。
创建了这个文件后,你可以在通过@anim/my_accelerate_interpolator来使用这个Interpolator。比如下面这个缩放的动画效果:
<scale xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@anim/my_accelerate_interpolator" android:fromXScale="0.0" android:toXScale="1.0" android:fromYScale="0.0" android:toYScale="1.0" android:duration="300" />
类名: LinearInterpolator
资源ID: @android:anim/linear_interpolator
XML标记: linearInterpolator
公式: y=t
构造函数: public LinearInterpolator()
属性: 无
类名: AccelerateInterpolator
资源ID: @android:anim/accelerate_interpolator
XML标记: accelerateInterpolator
公式: y=t^(2f)
构造函数: public AccelerateInterpolator(float factor)
参数:
名称: f
XML属性: android:factor
描述: 加速度参数. f越大,起始速度越慢,但是速度越来越快
类名: DecelerateInterpolator
资源ID: @android:anim/decelerate_interpolator
XML标记: decelerateInterpolator
公式: y=1-(1-t)^(2f)
构造函数: public DecelerateInterpolator(float factor)
参数:
名称: f
XML属性: android:factor
描述: 加速度参数. f越大,起始速度越快,但是速度越来越慢
类名: AccelerateDecelerateInterpolator
资源ID: @android:anim/accelerate_decelerate_interpolator
XML标记: accelerateDecelerateInterpolator
公式: y=cos((t+1)π)/2+0.5
构造函数: public AccelerateDecelerateInterpolator()
参数: 无
类名: AnticipateInterpolator
资源ID: @android:anim/anticipate_interpolator
XML标记: anticipateInterpolator
公式: y=(T+1)×t^3�CT×t^2
构造函数: public AnticipateInterpolator(float tension)
参数:
名称: T
XML属性: android:tension
描述: 张力值, 默认为2,T越大,初始的偏移越大,而且速度越快
类名: OvershootInterpolator
资源ID: @android:anim/overshoot_interpolator
XML标记: overshootInterpolator
公式: y=(T+1)x(t1)^3+T×(t1)^2 +1
构造函数: public OvershootInterpolator (float tension)
参数:
名称: T
XML属性: android:tension
描述: 张力值,默认为2,T越大,结束时的偏移越大,而且速度越快
类名: AnticipateOvershootInterpolator
资源ID: @android:anim/anticipate_overshoot_interpolator
XML标记: anticipateOvershootInterpolator
公式:
构造函数:
public AnticipateOvershootInterpolator(float tension)
public AnticipateOvershootInterpolator(float tension, float extraTension)
参数:
XML属性: android:tension
描述: 张力值,默认为2,张力越大,起始和结束时的偏移越大,而且速度越快
XML属性: android:extraTension
描述: 额外张力值,默认为1.5。公式中T的值为tension*extraTension
类名: BounceInterpolator
资源ID: @android:anim/bounce_interpolator
XML标记: bounceInterpolator
公式:
构造函数: public BounceInterpolator ()
参数: 无
类名: CycleInterpolator
资源ID: @android:anim/cycle_interpolator
XML标记: cycleInterpolator
公式: y=sin(2π×C×t)
构造函数: public CycleInterpolator(float cycles)
参数:
名称: C
XML属性: android:cycles
描述: 周期值,默认为1;2表示动画会执行两次
下面,我们就来创建自己的Interpolator。上面已经讲得非常清楚了,Interpolator的关键在于公式。我想创建的Interpolator名字叫HesitateInterPolator:起始时速度全速,快到一半时减速到0,然后加速直到终点,用图形来表示即:
用数学公式来表示即:
我们只需要实现Interpolator接口,然后实现其中的float getInterpolation(float t)接口即可:
public class HesitateInterpolator implements Interpolator { public HesitateInterpolator() {} public float getInterpolation(float t) { float x=2.0f*t-1.0f; return 0.5f*(x*x*x + 1.0f); } }
通过编程方式来使用自定义Interpolator很简单,比如:
ScaleAnimation scale = new ScaleAnimation(0.0f, 1.0f, 0.0f, 1.0f); scale.setInterpolator(new HesitateInterpolator());
这样就好了。遗憾的是,我们无法在XML资源中使用自定义Interpolator。