Android Animation和Animator之Interpolator

插值器

先上图吸引人,:p

在这里插入图片描述

在这里插入图片描述

  在Android动画中有一个很重要的工具,Interpolator,翻译过来就是插值器,这个词相信对上过数值分析这门课的同学都不会感到陌生,当初这门课是折腾的我欲仙欲死,然后发现工作了还是要被折磨 。好了,废话不多说,那么这个插值器的作用是什么呢?简单的来说就是,给你两个点A( x 1 x_1 x1, y 1 y_1 y1),B( x 2 x_2 x2, y 2 y_2 y2),你给我描绘出从A点到B点的曲线,说白了,就是给出A到B的函数曲线的表达式。而Android中View的动画,一般是由一个开始状态,和一个结束状态,Interpolator就是用来描述从开始到结束这中间的View的状态的。比如位移动画TranslationAnimation,从(0,0)水平移动到(100,0)的动画,如果使用线性插值器(LinearInterpolator),这种插值器View动画的属性(x轴坐标)随时间线性增长,所以是均速移动。

package android.animation;
/**
 * 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);
}

  好多人都把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.

翻译过来就是一个定义了动画改变速率的时间插值器,允许动画能做加速运动和加速运动等非线性运动, 看到动画改变速率似乎叫加速器好像没啥毛病,但是我们不能只看到改变速率 这几个字就认为这是加速器。事实上,getInterpolation返回的就是你需要定义的插值函数的返回值,它是一个动画执行的进度(也可以认为它是一种状态),插值函数 y = f ( x ) y=f(x) y=f(x) x ∈ [ 0 , 1 ] x\in[0,1] x[0,1] x = 0 x=0 x=0代表动画开始执行, x = 1 x=1 x=1代表动画执行结束。 y = 0 y=0 y=0代表动画开始执行View的状态, y = 1 y=1 y=1代表动画结束执行View的状态。例如,TranslationAnimation,将一个View从(0,0)水平移动到(100,0),那么动画开始View的状态就是View在(0,0)的位置,动画结束View的状态就是View在(100,0)的位置。
  所以Interpolator压根就不是动画改变的速率。那动画改变的速率是谁来决定的?是由你定义的插值函数决定的!动画改变的速率就是插值函数的一阶导数!所以它才是加速器。
  比如你的插值函数是线性函数 y = k x + b y=kx+b y=kx+b,那么动画的改变速率就是插值函数的一阶导数 y ′ y' y = k,就是常量,所以动画是匀速变化的;同样如果你定义一个二次函数 y = x 2 y=x^2 y=x2,那么动画的改变速率就是 y ′ = 2 ∗ x y'=2*x y=2x,它随着x的增加而增加,动画也会随着时间越变越快。
  Android中的所有Interpolator都要实现android.animation.TimeInterpolator接口,TimeInterpolator有一个接口函数float getInterpolation(float input),这个函数就是插值的函数曲线的表达式( y = F ( x ) y = F(x) y=F(x)的 F),但是需要你自己去实现。输入值就是自变量 x x x,范围是[0,1]。 x x x你可以认为它就是动画的执行时间,只不过android在这里把它归一化了。返回值就是y,这个y就是某一时间点 x 0 x_0 x0 对应的View的动画执行进度 y 0 y_0 y0 ,当然这里也是归一化之后的,至于如何将这个归一化的值映射到具体的属性上去,那就是Evaluator要干的活了,这个我们后面会再讲。注意返回值允许小于0,或者大于1。也就意味着,动画可以超出起始状态和结束状态。我们可以根据需求实现各种Interpolator,但是一般用android给我提供的也就够用了。

其实最简单的Evaluator也非常简单,这里可以简介一下。我们已经知道Interpolator返回的是一个动画的进度(百分比),那么这个进度其实就是

f r a c t i o n = ( V i e w 当 前 状 态 − 动 画 开 始 V i e w 的 状 态 ) ( 动 画 结 束 V i e w 的 状 态 − 动 画 开 始 V i e w 的 状 态 ) fraction =\frac{(View当前状态−动画开始View的状态)}{(动画结束View的状态 - 动画开始View的状态)} fraction=(ViewView(ViewView
再来看一下Evaluator的源码,

public interface TypeEvaluator<T> {
    /**
     * This function returns the result of linearly interpolating the start and end values, with
     * <code>fraction</code> representing the proportion between the start and end values. The
     * calculation is a simple parametric calculation: <code>result = x0 + t * (x1 - x0)</code>,
     * where <code>x0</code> is <code>startValue</code>, <code>x1</code> is <code>endValue</code>,
     * and <code>t</code> is <code>fraction</code>.
     *
     * @param fraction   The fraction from the starting to the ending values
     * @param startValue The start value.
     * @param endValue   The end value.
     * @return A linear interpolation between the start and end values, given the
     *         <code>fraction</code> parameter.
     */
    public T evaluate(float fraction, T startValue, T endValue);

}

文档写的很清楚了,而且都把代码给你说出来了,就是
r e s u l t = s t a r t V a l u e + f r a c t i o n ∗ ( e n d V a l u e − s t a r t V a l u e ) result= startValue + fraction*(endValue - startValue) result=startValue+fractionendValuestartValue
其中startValueendValue分别是动画开始和结束View的状态, fraction就是Interpolator传过来的动画进度值,返回的就是真实的View的状态了。所以Evaluator的作用就是接收Interpolator传递过来的fraction,并根据这个fraction以及View开始状态和结束时状态来计算动画进行中的状态。(其实这里我一直有个疑惑的,如果再Interpolator里面什么也不做,就是不设置Interpolator,在Evaluator里面去做一些对fraction的变换,比如二次方之类的,好像Evaluator就把Interpolator的活给干了,那还要Interpolator做什么?我猜测这样分开是为了各司其职吧。)

  Android已经给我提供了许多现成的Interpolator,常见的有:

name作用资源id
LinearInterpolator线性插值器,均匀变化@android:interpolator/linear
AccelerateInterpolator加速插值器,加速运动@android:interpolator/accelerate_cubic
DecelerateInterpolator减速插值器,减速运动@android:interpolator/decelerate_cubic
AccelerateDecelerateInterpolator加减速插值器,先加速,后减速@android:interpolator/accelerate_decelerate
BounceInterpolator回弹插值器,会产生类似乒乓球落地的弹跳效果@android:interpolator/bounce
OvershootInterpolator会越过终点然后回弹回来@android:interpolator/overshoot
AnticipateOvershootInterpolator会先反向越过起点,然后再折返,再越过终点,在这返回终点@android:interpolator/anticipate_overshoot
CycleInterpolator循环运动@android:interpolator/cycle
PathInterpolator贝塞尔曲线的效果,支持二阶三阶贝塞尔曲线

下面给出每个插值器的效果图,为了能更加清楚的演示出每种插值器的效果,我给目标View一个水平运动的动画,并且将水平运动的动画的interpolator设置为线性插值器,这样目标View就能沿着水平匀速运动。然后我给目标View一个垂直位移运动的动画,并且给动画设定不同的插值器,并将View的运动轨迹画出来,这样就能清楚的看到各种interpolator的效果。注意最终的轨迹是水平方向的运动和垂直方向运动的叠加,坐标系中绘制的是Interpolator的 y=F(x) 的曲线。(是不是发现曲线和运动轨迹好像一样啊?思考一下为什么。)

一个有意思的贝塞尔演示网站

https://cubic-bezier.com/#.55,-0.83,.4,1.87

1、LinearInterpolator

在这里插入图片描述

2、AccelerateInterpolator

在这里插入图片描述

3、AccelerateDecelerateInterpolator

在这里插入图片描述

4、BounceInterpolator

在这里插入图片描述

5、OvershootInterpolator

在这里插入图片描述

6、AnticipateOvershootInterpolator

在这里插入图片描述

7、CycleInterpolator

在这里插入图片描述

8、PathInterpolator

在这里插入图片描述

在这里插入图片描述

9、Other & 源码

Android LOLLIPOP(21)之后又引入FastOutLinearInInterpolator、FastOutSlowInInterpolator、LinearOutSlowInInterpolator三个插值器,其实原理都是一样的,都是实现了Interpolator接口,以上三个插值器本质上都是用的三阶贝塞尔曲线。
源码依旧在全球最大同性交友网站github,目录是me.fresh.lee.kotlintest.activity.InterpolatorActivity,代码主要是用Kotlin写的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值