我们在做动画的时候,总是避免不了会使用到 Interpolator(插值器)这个东西,比如 LinearInterpolator 等。这样做的好处是,能够让动画的变化速度符合现实世界中的物理规律,看上去更加逼真。比如汽车启动时,速度总是越来越快的。

Android SDK 提供有多种插值器供开发人员使用。但很多时候,由于我们的英语水平、数学水平等原因,总是无法直观地区分各种插值器之间的细微区别。

无意中看到国外友人的一篇文章。这篇文章使用公式和图解的形式细细分析了各种插值器下的变化规律。于是翻译过来,希望这种图文并茂的方式能够让我们加深对不同插值器的理解。

这篇文章我将向你展示,如何定制属于你自己的动画插值器。就像前面文章所讲的,动画系统已经提供了一系列的插值器供你选择。但是有时候你会有不一样的需求,并且你希望你的插值器有些微的不同。你可以改变已有的插值器甚至创建你自己的插值器。在文章末尾,我将创建一个新的 HesitateInterpolator 插值器作为示范。这个插值器使得动画全速启动,然后减速到一半,再加速直到动画结束。但是在此之前,我先讲讲插值器的理论知识,并向你展示如何定制已有的系统插值器。

一点理论知识


想要知道如何实现一个插值器之前,我们必须理解一个插值器到底做了什么。动画在开始时间和结束时间之间执行,每一帧都在这期间的一个特定时间显示。这个特定时间就是一个时间指数,0.0 到 1.0 闭区间中的一个 float 类型的数字。0.0 表示动画开始,1.0 表示动画结束。最简单的场景是,这个值直接被用于计算动画执行对象的变化。这种情况下,0.0 对应着动画的起始位置,1.0 对应着结束位置,0.5 表示一半,即起始位置和中间位置的正中间。这就是 LinearInterpolator(线性插值器)所做的事情。时间变化 30%,View 对应移动 30% 的距离。

一般来说,这个时间指数并不是直接用来计算动画的变化值。我们可以改变时间指数的值,使其以其他值的方式也能从 0.0 走到 1.0,而不是按照固定不变的方式运行。这就是插值器所做的事情。

一个时间插值器基本上也是一个数学公式,从 0.0 到 1.0 之间取一个值,然后变化为另一个值。下图向我们展示了加速度插值器的变化规律。View 以零速度启动,然后朝着结束位置加速变化。

默认情况下,加速度插值器的数学公式使用的是:

y = t2

这里的 y 值表示插值器的输出值,t 值表示时间指数。加速度插值器可以通过一个参数实现定制化。通常,加速度插值器使用的这个公式这样表示:

y = t2f

f 作为一个因子,用于强调加速度的的变化。f 值越大,意味着 View 启动越慢,然后以更快的速度结束。另一方面,f 值为 1 时展示出的效果与线性插值器(Linear Interpolator)一致。

定制化插值器


大部分系统插值器都可以使用 XML 资源文件或者动态编程的方式实现定制化。通过 XML 资源定制化插值器的话,你必须在 res/anim 目录下创建一个新的 XML 文件。比如,我们想修改加速度插值器,设置 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" />

注意:指定插值器的标签使用的是对应插值器的类名,但是第一个字母改为小写字母。然后你就可以像平时那样,在动画资源文件中简单地通过引用方式使用这个自定义的插值器:

@anim/my_accelerate_interpolator

举个例子,在 Scale 动画中使用:

<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" />

插值器一览


Linear Interpolator(线性插值器)

类名:

LinearInterpolator

资源 id:

@android:anim/linear_interpolator

标签名:

linearInterpolator

数学公式:

y = t

类构造函数:

public LinearInterpolator()

属性:

Accelerate Interpolator(加速度插值器)

类名:

AccelerateInterpolator

资源 id:

@android:anim/accelerate_interpolator

标签名:

accelerateInterpolator

数学公式:

y = t2f

类构造函数:

public AccelerateInterpolator(float factor)

参数:

名称:f

属性:android:factor

描述:加速度的变化速率

值越大,动画初始移动速度越慢,然后以更快的速度运动至结束。

Decelerate Interpolator(减速度插值器)

类名:

DecelerateInterpolator

资源 id:

@android:anim/decelerate_interpolator

标签名:

decelerateInterpolator

数学公式:

y = 1 - (1 - t)2f

类构造函数:

public DecelerateInterpolator(float factor)

参数:

名称:f

属性:android:factor

描述:减速度的变化速率。

值越大,动画初始移动速度越快,然后以更慢的速度运动至结束。

Accelerate Decelerate Interpolator(先加速后减速插值器)

类名:

AccelerateDecelerateInterpolator

资源 id:

@android:anim/accelerate_decelerate_interpolator

标签名:

accelerateDecelerateInterpolator

数学公式:

y = cos((t + 1)π)/2 + 0.5

类构造函数:

public AccelerateDecelerateInterpolator()

参数:

Anticipate Interpolator(张力加速器)

类名:

AnticipateInterpolator

资源 id:

@android:anim/anticipate_interpolator

标签名:

anticipateInterpolator

数学公式:

y = (T + 1) × t3 – T × t2

类构造函数:

public AnticipateInterpolator(float tension)

参数:

名称:T

属性:android:tension

描述:反向张力值,默认值为 2。

值越大,初始化反向张力越大,运动也越快

Overshoot Interpolator(越界加速器)

类名:

OvershootInterpolator

资源 id:

@android:anim/overshoot_interpolator

标签名:

overshootInterpolator

数学公式:

y = (T + 1) × (t - 1)3 + T × (t - 1)2 + 1

类构造函数:

public OvershootInterpolator(float tension)

参数:

名称:T

属性:android:tension

描述:越界数量值,默认值为 2。

值越大,越界越多,运动也越快

Overshoot Interpolator

类名:

AnticipateOvershootInterpolator

资源 id:

@android:anim/anticipate_overshoot_interpolator

标签名:

anticipateOvershootInterpolator

数学公式:



类构造函数:

- public AnticipateOvershootInterpolator(float tension)

- public AnticipateOvershootInterpolator(float tension, float extraTension)

参数:

属性:android:tension

描述:越界数量值,默认值为 2。

值越大,越界越多,运动也越快

属性:android:extraTension

描述:额外反向张力值,默认值为 1.5。

T 值为:tension * extraTension

Bounce Interpolator(弹性插值器)

类名:

BounceInterpolator

资源 id:

@android:anim/bounce_interpolator

标签名:

bounceInterpolator

数学公式:



类构造函数:

public BounceInterpolator()

参数:

* Cycle Interpolator*(弹性插值器)

类名:

Cycle Interpolator

资源 id:

@android:anim/cycle_interpolator

标签名:

cycleInterpolator

数学公式:

y = sin(2π × C × t)

类构造函数:

public CycleInterpolator(float cycles)

参数:

名称:C

属性:android:cycles

描述:循环次数,默认值为 1.

创建新的插值器


正如上面所言,插值器本质上展示的是一个数学公式。要想创建一个属于你自己的插值器类,你必须实现 Interpolator 接口。这个接口只定义了一个方法:

float getInterpolation(float t) 

用于公式中的计算。举个例子,我想创建一个名为 HesitateInterpolator 的插值器,动画以最快的速度启动,然后减速运动至一半,最后加速运动至结束。运动曲线如图所示:

对应数学公式为:

y=0.5 × ((2t − 1)3+1)

HesitateInterpolator 类的代码也很简单:

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);
  }
}

使用这个插值器时,你只需要通过动态编程的方式将其添加到你的 View 动画中去:

ScaleAnimation scale = new ScaleAnimation(0.0f, 1.0f, 0.0f, 1.0f);
scale.setInterpolator(new HesitateInterpolator());

就是这些!不需要任何额外代码。

不幸的事,你不能在 XML 动画资源中使用这个插值器,只支持动态编程的方式。

GIF 图效果


上面所述便是翻译原文的全部部分。最后再附上几张 Gif 图,也来自国外友人的博客,通过对比的形式更加直观地查看不同插值器的作用效果:

  • Accelerate Decelerate, Accelerate, Anticipate & Anticipate Overshoot:

  • Bounce, Decelerate, Fast Out Linear In & Fast Out Slow In:

  • Fast Out Slow In, Linear, Linear Out Slow In & Overshoot

参考链接


英文原文:Android Animations Tutorial 5: More on Interpolators

Gif 图来源:Android Interpolators: A Visual Guide

关于我:亦枫,博客地址:http://yifeng.studio/,新浪微博:IT亦枫

微信扫描二维码,欢迎关注我的个人公众号:安卓笔记侠

不仅分享我的原创技术文章,还有程序员的职场遐想

【译】从数学公式入手,详细了解 Animation 的 Interpolators的更多相关文章

  1. 2018年1月17日总结 css3里transition 和animation 区别

    transition 和animation两个CSS3属性经常被用到实际项目中,想把它整理出来. 1.先介绍transition >>>>>  a. 在做项目中经常会遇见 ...

  2. 11.IntelliJ IDEA详细配置和使用教程(适用于Java开发人员)

    转自:https://blog.csdn.net/chssheng2007/article/details/79638076 前言 正所谓工欲善其事必先利其器,对开发人员而言若想提高编码效率,一款高效 ...

  3. IntelliJ IDEA详细配置和使用教程(适用于Java开发人员)

    关闭Intellij IDEA自动更新在File->Settings->Appearance & Behavior->System Settings->Updates下 ...

  4. Java 在Word中添加数学公式(Latex/MathML)

    本文介绍通过Java程序在Word文档中添加数学公式的方法.添加时,可添加latex数学公式或者MathML数学公式.详细内容见下文. 1. 程序环境 Word测试文档:.docx 2013 Word ...

  5. 一篇博客带你入门Flask

    一. Python 现阶段三大主流Web框架 Django Tornado Flask 对比 1.Django 主要特点是大而全,集成了很多组件,例如: Models Admin Form 等等, 不 ...

  6. android 属性动画

    一直再追郭霖的博客和imooc上的一些新的视频,最近有讲到属性动画. 以下内容为博客学习以及imooc上视频资料的学习笔记: 在3.0之前比较常见的动画为tween动画和frame动画: tween动 ...

  7. babel如此简单

    凡是看到这个标题点进来的同学,相信对babel都有了一定的了解.babel使用起来很简单,简单到都没有必要写一篇文章去介绍,直接看看官方文档就可以.所以我也在怀疑到底该不该写这篇文章.想来想去还是决定 ...

  8. babel从入门到入门

    babel从入门到入门 来源 http://www.cnblogs.com/gg1234/p/7168750.html 博客讲解内容如下: 1.babel是什么 2.javascript制作规范 3. ...

  9. babel简介

    1.babel是什么 babel官网正中间一行黄色大字写着“babel is a javascript compiler”,翻译一下就是babel是一个javascript转译器.为什么会有babel ...

随机推荐

  1. 20145309《Java程序设计》第八周学习总结

    日志 •java.util.logging包提供了日志功能相关类与接口,使用日志的起点是logger类,Logger类的构造函数标示为protected,不是java.util.logging同包的类 ...

  2. strcpy、sprintf、memcpy的区别

    char*strcpy(char *dest, const char *src); 其对字符串进行操作,完成从源字符串到目的字符串的拷贝,当源字符串的大小大于目的字符串的最大存储空间后,执行该操作会出 ...

  3. [JavaWeb]关于DBUtils中QueryRunner的一些解读(转)

    QueryRunner类 QueryRunner中提供对sql语句操作的API它主要有三个方法 query() 用于执行select update() 用于执行insert/update/delete ...

  4. An Example for Javascript Function Scoping and Closure

    1. An Real World Example In the patron detail page of the CRM system I'm working with, there’re larg ...

  5. IDEA 逆向工程

    今天要写一个导入功能,需要把数据库的一个表映射成一个pojo,但是这表字段不是一般的多啊...想了想能不能自动生成???在IDEA中点了半天发现还是可以的 下面介绍一下步骤: 第一步:找到这个图标,建 ...

  6. String中的equals方法解析 jdk1.7

    注  此篇为jdk1.7中的源码解析 equals()方法中的判断分一下步骤 1先判断内存地址是否相同  如果内存地址相同 那么字符串就是相同的 返回true 2 判断当前字符串和参数字是否属于同一类 ...

  7. LeetCode——Nth Digit

    Question Find the nth digit of the infinite integer sequence 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ... ...

  8. 关于C# get set的简单用法

    关于C# get set的文章很多,但是笔者的这篇文章有它的特别之处,笔者用简单的语言把c# get set讲述的十分明了. C# get set释一:属性的访问器包含与获取(读取或计算)或设置(写) ...

  9. OnClickListener两种监听方法

    //1种:接口OnClickListener ,在onclick响应 public class MainActivity extends Activity implements OnClickList ...

  10. sickit-learn库实现机器学习

    sickit-learn库实现机器学习 [TOC] Iris数据集 from sklearn import datasets iris=datasets.load_iris() # 数据 iris.d ...