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

作者: 墨源为水 | 来源:发表于2016-06-17 16:07 被阅读175次

    插值器介绍

    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](https://img.haomeiwen.com/i2244681/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

    相关文章

      网友评论

        本文标题:android动画学习(2)一Tween动画的插值器

        本文链接:https://www.haomeiwen.com/subject/hszmdttx.html