动画插值器Interpolator

QuibblerQuibbler 2020-09-03 约 30 分钟 2000 次阅读

动画插值器Interpolator

Animation中一个重要的概念是Interpolator插值器,动画执行的速率加上效果(加速或者减速等等),让动画执行起来不那么“死板”,动画看起来能够更自然“活泼”。想要实现炫酷好看的动画离不开插值器。后面讲到属性动画还会学习估值器TypeEvaluator,详见《属性动画:TypeEvaluator》。

1、Interpolator

了解Interpolator用途及其接口定义。对源码熟悉的会发现,在 android.graphics 包中也有一个同名的Interpolator类而非接口。

1.1、介绍

插值器指定了如何根据时间计算动画中的特定值。例如,您可以指定动画在整个动画中以线性方式播放,即动画在整个播放期间匀速移动;也可以指定动画使用非线性时间,例如动画在开始后加速并在结束前减速。

动画系统中的插值器会接收来自 Animator的分数,该分数表示动画的已播放时间。插值器会修改此分数,使其与要提供的动画类型保持一致。

1.2、接口

Interpolator接口在 android.view.animation 包中,继承自TimeInterpolator接口

package android.view.animation;
    import android.animation.TimeInterpolator;
    /**
     * An interpolator defines the rate of change of an animation. This allows
     * the basic animation effects (alpha, scale, translate, rotate) to be 
     * accelerated, decelerated, repeated, etc.
     */
    public interface Interpolator extends TimeInterpolator {
        // 为新的android.animation包引入了新接口TimeInterpolator。 
        //这个较旧的Interpolator接口扩展了TimeInterpolator,
        //因此基于Animator的新动画的用户可以使用旧的Interpolator实现或直接实现TimeInterpolator的新类。
    }

TimeInterpolator接口在 android.animation 包中,定义了float getInterpolation(float input)接口方法,后面自定义插值器需要实现该方法。输入参数的值input范围在0~1,0动画开始,0.5动画执行一半,1动画执行完毕。

package android.animation;
    /**
     * 时间插值器定义动画的变化率。 这允许动画进行非线性运动,例如加速和减速。
     */
    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);
    }

2、内置Interpolator

Android系统在 android.view.animation 包中提供了一组常用的插值器。了解一下它们是如何实现的,借助函数图像绘制工具或数学网在线函数图像生成或Desmos图形计算器看看getInterpolation(float input)方法中的数学函数。

2.1、BaseInterpolator*

        系统内置插值器扩展自该抽象类BaseInterpolator 

package android.view.animation;
    import android.content.pm.ActivityInfo.Config;
    /**
     * 系统内置插值器扩展自该抽象类BaseInterpolator。
     */
    abstract public class BaseInterpolator implements Interpolator {
        private @Config int mChangingConfiguration;
        /**
         * @hide
         */
        public @Config int getChangingConfiguration() {
            return mChangingConfiguration;
        }
        /**
         * @hide
         */
        void setChangingConfiguration(@Config int changingConfiguration) {
            mChangingConfiguration = changingConfiguration;
        }
    }

2.2、AccelerateDecelerateInterpolator 

AccelerateDecelerateInterpolator:先加速,后加速

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

函数:(cos((x + 1) * π) / 2.0) + 0.5

2.3、AccelerateInterpolator

AccelerateInterpolator:加速插值器

public float getInterpolation(float input) {
        if (mFactor == 1.0f) {
            return input * input;
        } else {
            return (float)Math.pow(input, mDoubleFactor);
        }
    }

函数:pow(x,2)

2.4、AnticipateOvershootInterpolator

AnticipateOvershootInterpolator:在动画开始时向前偏移一段距离,在动画结束后向后偏移一段距离。

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

函数:0.5*2*x * 2*x * ((3 + 1) * 2*x - 3)                          (0 < x < 0.5)

0.5*((2*x-2) * (2*x-2) * ((3 + 1) * (2*x-2) + 3)+2)  (0.5 <= x < 1.0)


2.5、LinearInterpolator

LinearInterpolator:线性插值器,运距加速器。默认的动画效果。

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

函数:x

2.6、PathInterpolator

PathInterpolator:新增的Path路径插值器,使用它可以非常方便的创建二阶、三阶的贝塞尔曲线动画。

2.7、BounceInterpolator

BounceInterpolator:模拟自由落体反复回弹最终落地的动画效果。

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

函数:x * x * 8.0,                                      (x < 0.3535)

(x-0.54719)* (x-0.54719)* 8+0.7,   (x < 0.7408)

(x-0.8526)* (x-0.8526)* 8+0.9,       (x < 0.9644)

(x-1.0435)* (x-1.0435)* 8+0.95      (x = 其他)


2.8、OvershootInterpolator

OvershootInterpolator:在动画结束时,继续沿着既定动画路径执行一段距离在结束动画,回到最终位置。

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

函数:0.5*2*x * 2*x * ((3 + 1) * 2*x - 3)                          (0 < x < 0.5)

0.5*((2*x-2) * (2*x-2) * ((3 + 1) * (2*x-2) + 3)+2)  (0.5 <= x < 1.0)


2.9、CycleInterpolator

CycleInterpolator:循环插值器。动画循环播放特定的次数。

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

函数:sin(2 * 1* π * x)

2.10、AnticipateInterpolator

AnticipateInterpolator:动画开始时一开始先向后一段距离,然后开始加速。

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

函数:x * x * ((2+ 1) * x - 2)

2.11、DecelerateInterpolator

DecelerateInterpolator:加速插值器。一开始动画速度最大,然后逐渐变慢。

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

函数:1.0 - pow((1.0 - x), 2 * 1)

4、使用Interpolator

使用Interpolator很简单,创建需要的插值器类型,然后调用setInterpolator(Interpolator i)方法设置给Animation对象即可。

mAnimation.setInterpolator(interpolator)

另外还可以直接在xml动画文件中设置动画的插值器

android:interpolator="@android:anim/accelerate_decelerate_interpolator"
    android:interpolator="@android:anim/accelerate_interpolator"
    android:interpolator="@android:anim/anticipate_interpolator
    android:interpolator="@android:anim/anticipate_overshoot_interpolator
    android:interpolator="@android:anim/bounce_interpolator
    android:interpolator="@android:anim/cycle_interpolator
    android:interpolator="@android:anim/decelerate_interpolator
    android:interpolator="@android:anim/linear_interpolator
    android:interpolator="@android:anim/overshoot_interpolator

4.1、AccelerateDecelerateInterpolator

构造

new AccelerateDecelerateInterpolator();

4.2、AccelerateInterpolator

构造

AccelerateInterpolator()
    /**
     * 动画应缓和的程度。 
     * 将系数设置为1.0f会产生y = x ^ 2抛物线。 
     * 大于1.0f的因数会放大缓入效果(即开始时更慢,结束时甚至更快)
     */
    AccelerateInterpolator(float factor)

4.3、AnticipateOvershootInterpolator

构造

//mTension默认为2.0f * 1.5f
    public AnticipateOvershootInterpolator() {
        mTension = 2.0f * 1.5f;
    }
    
    /**
     * @param tension 预期/超量。 当张力等于0.0f时,就不会有预期/超调,并且插补器将成为简单的加减速插补器。
     */
    public AnticipateOvershootInterpolator(float tension) {
        mTension = tension * 1.5f;
    }
    
    /**
     * @param tension 预期/超量。当张力等于0.0f时,就不会有预期/超调,并且插补器将成为简单的加减速插补器。
     * @param extraTension 乘以张力的量。例如,要以2.0f的张力获得与OvershootInterpolator相同的超调,可以使用1.5f的extraTension。
     */
    public AnticipateOvershootInterpolator(float tension, float extraTension) {
        mTension = tension * extraTension;
    }

4.4、LinearInterpolator

构造

public LinearInterpolator() {
    }

4.5、PathInterpolator

构造,

//注意The Path must start at (0,0) and end at (1,1)
    PathInterpolator(Path path)
    
    //为二次贝塞尔曲线创建一个插值器,假定为端点(0,0)和(1,1)
    PathInterpolator(float controlX, float controlY)
    
    //为三次贝塞尔曲线创建一个插值器,假定为端点(0,0)和(1,1)
    PathInterpolator(float controlX1, float controlY1, float controlX2, float controlY2)

例:new PathInterpolator(0.5f, 0.6f, .8f, .3f)

4.6、BounceInterpolator

构造

public BounceInterpolator() {
    }

4.7、OvershootInterpolator

构造

public OvershootInterpolator() {
        mTension = 2.0f;
    }
    
    /**
     * @param 张力过冲量。当张力等于0.0f时,不会出现过冲,并且插补器将成为简单的减速插补器。
     */
    public OvershootInterpolator(float tension) {
        mTension = tension;
    }

4.8、CycleInterpolator

构造

public CycleInterpolator(float cycles) {
        mCycles = cycles;
    }

4.9、AnticipateInterpolator

构造

public AnticipateInterpolator() {
        mTension = 2.0f;
    }
    /**
     * @param tension 预期量。 当张力等于0.0f时,没有预期值,并且插值器变为简单的加速度插值器。
     */
    public AnticipateInterpolator(float tension) {
        mTension = tension;
    }

4.10、DecelerateInterpolator

构造

public DecelerateInterpolator() {
    }
    
     /**
     * @param factor 动画应缓和的程度。 将系数设置为1.0f会产生上下颠倒的y = x ^ 2抛物线。
     * 大于1.0f的因数会放大缓和效果(即开始时更快,结束时甚至更慢).
     */
    public DecelerateInterpolator(float factor) {
        mFactor = factor;
    }

5、自定义Interpolator

如果上面系统自带的插值器都不能满足开发需求,那么可以实现Interpolator接口自定义插值器,实现getInterpolation(float input)方法

public class QuibblerInterpolator implements Interpolator {
        private float factor = 2.0f;
        
        public QuibblerInterpolator() {
        }
        
        public QuibblerInterpolator(float factor) {
            this.factor = factor;
        }
        
        @Override
        public float getInterpolation(float input) {
            return (float) (Math.pow(2.0, -10.0 * input) * Math.sin((input - factor / 4) * (2 * Math.PI) / factor) + 1);
        }
    }

但是不要实现TimeInterpolator接口,因为会发现Animation设置Interpolator方法的参数是Interpolator而不是父接口TimeInterpolator。

/**
     * Sets the acceleration curve for this animation. Defaults to a linear
     * interpolation.
     *
     * @param i The interpolator which defines the acceleration curve
     * @attr ref android.R.styleable#Animation_interpolator
     */
    public void setInterpolator(Interpolator i) {
        mInterpolator = i;
    }

参考博客:

         Docs > Reference > Interpolator">Android Developers > Docs > Reference > Interpolator

        几种常用的Interpolator(插值器)的动画效果

         Use Interpolators">Property Animation Overview > Use Interpolators

        Timing is Everything

        Interpolator插值器详解

        Android Interpolator属性 设置动画速度

        Android中的Interpolator

        让View具有弹性效果的动画——SpringAnimation

        PathInterpolator

        Android 动画的Interpolator插值器

        Android动画插值器之PathInterpolator浅析

        函数绘制工具

        介绍以及自定义Interpolator插值器


相关推荐

精选
ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager
Android

ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager

ViewPager1、ViewPagerandroidx.viewpager.widget.ViewPager,Android中使用非常广泛的控件,可以说是APP必备:首次打开引导页、页面Banner广告等。常用方法:setAdapter() 设置适配器setOffscreenPageLimit() 设置缓存的页面个数,默认是 1setCurrentItem() 跳转到特定的页面setOnPage

1.1k
获取Android内置WebView内核版本
Android

获取Android内置WebView内核版本

获取Android内置WebView内核版本竟然能遇到这样奇葩的事情,网页用的技术过于新颖,以至于只支持高版本Chromium内核的,低版本安卓系统中内置的内核版本较低,无法加载前端页面。1、设置查看在系统设置里 > 应用 > 应用管理 > 显示系统应用,查看WebView组件:2、页面查看通过WebView发起的网络请求,都会带上浏览器的UA,通常页面都可以通过UA判断浏览器的内核版本。这里有两

1.1w
Android 14适配总结
Android

Android 14适配总结

Android 14适配总结毕业工作至今已经适配了三个Android大版本,从Android 11到Android 12、再到Android 13。2023年,Google即将推出的Android 14,上半年已经开始第一批适配。现在,第四个Android版本已经适配完,总结记录一下。1、Android 14计划Google一般会在2月份对外发布预告,同时放出开发者预览版。“拉通”各大平台、厂商以

1.1w