欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android 动画(三)Interpolator 插值器

程序员文章站 2022-05-18 08:33:55
...

概念:

插值器定义动画中特定值如何作为时间的函数进行计算。例如,可以指定动画在整个动画中线性发生,这意味着动画会平均移动整个时间,或者可以指定动画以使用非线性时间,例如在开始或结束时使用加速或减速动画。

使用插值器Interpolator改变动画运行的速度:

动画系统中的插值器会接收到动画已用时间的百分比。插值器根据这个时间百分比计算动画的实际想要显示的进度,注意该数值进度也是百分比的,并不是实际的值。从动画的时间百分比计算动画进度百分比的这一过程可以添加一些算法,从而实现各种效果的插值器,Android系统提供了一组常用的插值器。当然了我们也可以自己实现自定义Interpolator。

Interpolator explain
AccelerateDecelerateInterpolator 其变化率在动画开始和动画结束时比较缓慢,在中间的时候加速。ResourceID:@android:anim/accelerate_decelerate_interpolator
AccelerateInterpolator 其中动画开始的时候变化率比较缓慢,然后加速。AccelerateInterpolator(float factor)float:动画应该放松的程度。将因子设置为1.0f会产生ay = x ^ 2抛物线。增加1.0f以上的因子夸大了缓解效应(即,它开始更慢,结束更快)ResourceID:@android:anim/accelerate_interpolator
AnticipateInterpolator 开始的时候向后运动一段时间然后向前加速运动public AnticipateInterpolator(float tension)tension:预期的数量。当张力等于0.0f时,没有预期,插补器变成简单的加速度插值器。ResourceID:@android:anim/anticipate_interpolator
AnticipateOvershootInterpolator 开始的时候向后运动,然后向前运动并超过目标值,最后返回到最终值ResourceID:@android:anim/anticipate_overshoot_interpolator
DecelerateInterpolator 在动画开始的地方快然后慢ResourceID:@android:anim/decelerate_interpolator
CycleInterpolator 将动画重复指定的循环次数。变化率遵循正弦曲线。CycleInterpolator(float cycles)ResourceID:@android:anim/cycle_interpolator
LinearInterpolator 以常量速率改变 ResourceID:@android:anim/linear_interpolator
OvershootInterpolator 向前运动一定值后再回到原来位置ResourceID:@android:anim/overshoot_interpolator
BounceInterpolator 动画结束的时候弹起然后再落下ResourceID:@android:anim/bounce_interpolator

使用Android系统提供的Interpolator:

在xml代码中设置android:interpolator属性

<?xml version="1.0" encoding="utf-8"?>  
<scale xmlns:android="http://schemas.android.com/apk/res/android"  
    android:fromXScale="0.5"  
    android:toXScale="1.5"  
    android:fromYScale="0.5"  
    android:toYScale="1.5"  
    android:pivotX="50%"  
    android:pivotY="50%"  
    android:interpolator="@android:anim/accelerate_decelerate_interpolator" 
    android:repeatCount="3"
    android:repeatMode="reverse"
    android:duration="1000" />  

在java代码中使用

    private void ScaleAnimation() {
        ScaleAnimation scaleAnimation = new ScaleAnimation(0.5f, 1.5f, 0.5f, 1.5f, Animation.RELATIVE_TO_SELF, 1.0f, Animation.RELATIVE_TO_SELF, 1.0f);
        scaleAnimation.setDuration(1000);
        scaleAnimation.setRepeatCount(3);
        scaleAnimation.setInterpolator(new AccelerateDecelerateInterpolator());
        scaleAnimation.setRepeatMode(Animation.REVERSE);
        ivImage.startAnimation(scaleAnimation);
    }

Interpolator源码分析:

首先先研究下系统提供的线性插值器是如何实现的:
LinearInterpolator.java

public class LinearInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {

    public LinearInterpolator() {
    }

    public LinearInterpolator(Context context, AttributeSet attrs) {
    }

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

    /** @hide */
    @Override
    public long createNativeInterpolator() {
        return NativeInterpolatorFactoryHelper.createLinearInterpolator();
    }
}

LinearInterpolator继承自BaseInterpolator 这个抽象类,而BaseInterpolator 实现了Interpolator 接口

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

Interpolator 接口继承自TimeInterpolator接口 ,而TimeInterpolator接口仅有一个getInterpolation()方法。

public interface Interpolator extends 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.
*/
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);
}

可以看到TimeInterpolator 中只有一个函数 float getInterpolation(float input);
参数 input:input 参数是一个 float 类型,它取值范围是 0 到 1,表示当前动画的时间进度百分比,取 0 时表示动画刚开始,取 1 时表示动画结束,取 0.5 时表示动画中间的位置,其它类推。 返回值:表示当前实际想要显示的进度。取值可以超过 1 也可以小于 0,超过 1 表示已经超过目标值,小于 0 表示小于开始位置。
input 参数相当于时间的概念,我们通过 setDuration()指定了动画的时长,在这个时间范围内,动画进度肯定是一点点增加的;就相当于我们播放一首歌,这首歌的进度是从 0 到 1 是一样的。 而返回值则表示动画的数值进度,它的对应的数值范围是我们通过 ofInt(),ofFloat()来指定的,这个返回值就表示当前时间所对应的显示的进度。




LinearInterpolator 类继承自BaseInterpolator ,它实现getInterpolation()方法时比较简单,直接把 input 值返回,即以当前动画的时间进度作为动画的显示进度,这也就表示当前动画的显示进度与动画的时间进度一致,比如,如果当前动画进度为 0,那动画的显示进度也是 0,那如果动画进度为 0.5,那动画的显示进度也是在 0.5,当动画结束,动画的进度就变成 1 了,而动画的显示进度也是 1 了。而AccelerateInterpolator 插值器的动画的数值进度是由input * input实现的,所以会产生加速动画进度的效果。

public class LinearInterpolator extends BaseInterpolator {

    ...

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

}
public class AccelerateInterpolator extends BaseInterpolator {

    ...

    public float getInterpolation(float input) {
        if (mFactor == 1.0f) {
            return input * input;
        } else {
            return (float)Math.pow(input, mDoubleFactor);
        }
    }
}
相关标签: Interpolator 插值