android动画学习(2)一Tween动画的插值器

插值器介绍

Tween动画的插值器Interpolator,它用于修改一个动画过程中的速率,可以定义各种各样的非线性变化函数,比如加速、减速等。在Android中所有的插值器都是Interpolator 的子类,通过 android:interpolator 属性你可以引用不同的插值器。
Android中interpolator最底层的接口如下:

public interface TimeInterpolator { 
    //将动画已经消耗的时间的分数映射到一个表示插值的分数, 然后将插值与动画的变化值相乘来推导出当前已经过去的动画时间的动画变化量。
    @param input 一个0到1.0表示动画当前点的值,0表示开头。1表示结尾
    @return 插值。它的值可以大于1来超出目标值,也小于0来冲破底线。
    float getInterpolation(float input);
}

TimeInterpolator是在Android API11时加入的之前类就叫Interpolator。现在Interpolatro继承了它。

//一个定义动画变化率的插值器。 * 它允许对基本的(如透明,缩放,平移,旋转)进行加速,减速,重复等动画效果 
public interface Interpolator extends TimeInterpolator { 
}

系统提供了基本的插值器如下:



你可以通过下面的方式使用它们

<set android:interpolator="@android:anim/accelerate_interpolator"> ... </set>

如果你对系统提供的插值器不满意,我们可以创建一个插值器资源修改插值器的属性,比如修改AnticipateInterpolator的加速速率,调整accelerateInterpolator 的加速率等。为了完成这种需求,我们需要创建XML资源文件,然后将其放于/res/anim下,然后再动画元素中引用即可。

<accelerateInterpolator xmlns:android="http://schemas.android.com/apk/res/android"    
    android:factor="2" >
</accelerateInterpolator>

我们先来看一下几种常见的插值器可调整的属性:

<accelerateDecelerateInterpolator> 无
<accelerateInterpolator> android:factor 浮点值,加速速率,默认为1
<anticipateInterploator> android:tension 浮点值,起始点后退的张力、拉力数,默认为2
<anticipateOvershootInterpolator> android:tension 同上 android:extraTension 浮点值,拉力的倍数,默认为1.5(2 * 1.5)
<bounceInterpolator> 无
<cycleInterplolator> android:cycles int,循环的个数,默认为1
<decelerateInterpolator> android:factor 浮点值,减速的速率,默认为1
<linearInterpolator> 无
<overshootInterpolator> 浮点值,超出终点后的张力、拉力,默认为2 

如果简单的修改插值器的属性值还不能够满足我们的需求,那么就自己来通过实现Interpolator接口来定义自己的插值器了
因为上面所有的Interpolator都实现了Interpolator接口,这个接口定义了一个方法:float getInterpolation(float input);
此方法由系统调用,input代表动画的时间,在0和1之间,也就是开始和结束之间。
eg.

线性(匀速)插值器定义如下:
public float getInterpolation(float input) { 
     return input; 
}
加速减速插值器定义如下:
public float getInterpolation(float input) { 
     return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
}

系统提供简单插值器

1. AccelerateInterpolator 加速插值器

在这里我只分析AccelerateInterpolator的源码,便于我们可自定义插值器

public class AccelerateInterpolator implements Interpolator { 
     private final float mFactor; 
     private final double mDoubleFactor; 
     public AccelerateInterpolator() {      
         mFactor = 1.0f;        
         mDoubleFactor = 2.0;   
     } 
     // 动画的快慢度。将factor设置为1.0f会产生一条y=x^2的抛物线。增加factor到1.0f之后为加大这种渐入效果(也就是说它开头更加慢,结尾更加快)
      public AccelerateInterpolator(float factor) {     
          mFactor = factor;     
          mDoubleFactor = 2 * mFactor;  
      } 
      public AccelerateInterpolator(Context context, AttributeSet attrs) {      
          TypedArray a = context.obtainStyledAttributes(attrs,com.android.internal.R.styleable.AccelerateInterpolator);
          mFactor = a.getFloat(com.android.internal.R.styleable.AccelerateInterpolator_factor, 1.0f);       
          mDoubleFactor = 2 * mFactor;      
          a.recycle();  
     } 
     @Override 
     public float getInterpolation(float input) { 
          if (mFactor == 1.0f) { 
               return input * input;        
          } else { 
               return (float)Math.pow(input, mDoubleFactor);        
          } 
     }
}

factor值默认为1是:y=x^2,x即为input(0<x<=1),y为插值,函数图像如下:

%{BO)%UKFDOOF($WZ{_B90U.png

当我把factor设定为4时:y = x^(2*4),函数图像如下

EQQZ7H%LYHB$ZZ1BPMC{U}1.png

两者函数图像比较克制,当factor值越大,它就越表现为:先开始越慢,到最后突然变快。所以当我们想要这样的效果是,可以自定义AccelerateInterpolator插值器,将factor修改较大即可。

2. DecelerateInterpolator 减速插值器

@Override 
public float getInterpolation(float input) { 
     float result; 
     if (mFactor == 1.0f) {         
          result = (1.0f - ((1.0f - input) * (1.0f - input)));      
     } else {           
          result = (float)(1.0f - Math.pow((1.0f - input), 2 * mFactor));       
     } 
     return result; 
}

它的公式为:y = 1-(1-x)^(2*factor)
当factor值默认为1是:y=1-(1-x)^2时,函数图像如下:

5}FRSEJ~75U3HNYKYQ{~X~4.png

当fractor增大到4时,曲线轨迹如下图:
![Z_29H]%IH@1Y3BN53HQU9.png](http://upload-images.jianshu.io/upload_images/2244681-6f0037de3b0a69f1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

3. AccelerateDecelerateInterpolator 加速减速插值器 (开始,和结尾都很慢,但是,中间加速)

@Override 
public float getInterpolation(float input) { 
     return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f; 
} 

它的公式是:y=(1/2)(cos(x+1)*π+1),函数图像如下:


4. LinearInterpolator 线性插值器

public float getInterpolation(float input) { 
return input; 
}

5. BounceInterpolator 弹跳插值器 (结束的时候弹一下)

private static float bounce(float t) { 
return t * t * 8.0f;    
} 
@Override 
public float getInterpolation(float t) { 
     // _b(t) = t * t * 8 
     // bs(t) = _b(t) for t < 0.3535 
     // bs(t) = _b(t - 0.54719) + 0.7 for t < 0.7408 
     // bs(t) = _b(t - 0.8526) + 0.9 for t < 0.9644 
     // bs(t) = _b(t - 1.0435) + 0.95 for t <= 1.0 
     // b(t) = bs(t * 1.1226) t *= 1.1226f; 
     if (t < 0.3535f) return bounce(t); 
     else if (t < 0.7408f) return bounce(t - 0.54719f) + 0.7f; 
     else if (t < 0.9644f) return bounce(t - 0.8526f) + 0.9f; 
     else return bounce(t - 1.0435f) + 0.95f;   
}

6. AnticipateInterpolator 回荡秋千插值器 (开始向后一点,然后,往前抛)

@Override 
public float getInterpolation(float t) { 
// a(t) = t * t * ((tension + 1) * t - tension) 
     return t * t * (((mTension + 1) * t) - mTension);  
}

7. AnticipateOvershootInterpolator (开始向后一点,往前抛过点,然后返回来 )

private static float a(float t, float s) { 
     return t * t * (((s + 1) * t) - s);    
} 
private static float o(float t, float s) { 
     return t * t * (((s + 1) * t) + s);    
} 
@Override 
public float getInterpolation(float t) { 
     // a(t, s) = t * t * ((s + 1) * t - s) 
     // o(t, s) = t * t * ((s + 1) * t + s) 
     // f(t) = 0.5 * a(t * 2, tension * extraTension), when t < 0.5 
     // f(t) = 0.5 * (o(t * 2 - 2, tension * extraTension) + 2), when t <= 1.0 
     if (t < 0.5f) return 0.5f * a(t * 2.0f, mTension); 
     else return 0.5f * (o((t * 2.0f) - 2.0f, mTension) + 2.0f);    
}

8. CycleInterpolator 正弦周期变化插值器

@Override 
public float getInterpolation(float input) { 
     return (float)(Math.sin(2 * mCycles * Math.PI * input));   
}

9. OvershootInterpolator (往前抛超过一点,然后返回来)

@Override 
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; 
     //plot {(x-1)(x-1)((tension+1)(x-1)+tension)+1,(0<x<=1)} 
}

该篇文章参考了android动画(一)Interpolator

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容