Android自定义控件入门到精通--Interpolation插值器

本文详细介绍了Android中各种插值器的原理与实现,包括LinearInterpolator、AccelerateInterpolator、DecelerateInterpolator等,通过数学公式解析了它们如何控制动画的加减速效果。此外,还探讨了自定义插值器的方法,帮助开发者深入理解Android动画系统。
摘要由CSDN通过智能技术生成

《Android自定义控件入门到精通》文章索引 ☞ https://blog.csdn.net/Jhone_csdn/article/details/118146683

《Android自定义控件入门到精通》所有源码 ☞ https://gitee.com/zengjiangwen/Code

Interpolation插值器

在补间动画的介绍中,我们使用了Interpolator,Interpolator是用于控制动画如何运动的作用。

物体的运动我们知道有匀速运动和变速运动,匀速运动比较简单,物体从A到B运动速度是一样的,变速运动就比较复杂了,有先快后慢,先慢后快等各种情况,
在动画运用中,我们就是通过interpolator来控制(描述)动画的运动过程。

我们用t来表示当前动画运动的时间,t∈[01],用y来表示当前运动距离的百分比,y∈[01]

举例:

匀速运动,y=t

整个运动过程我们用y、t坐标系画出来应该就是一条直线

在这里插入图片描述

反过来,给出一条y、t曲线/直线,就能知道这个物体从起点到终点的运动过程,线上点的斜率反应当前的速度,斜率越大,当前速度越大,Interpolator就是用来定义这条直线的算法的

Anroid中的Interpolator实现了TimeInterpolator接口

public interface TimeInterpolator {
    float getInterpolation(float input);
}

getInterpolation() 描述的就是运动的公式(算法),自定义插值器只要在这里描述运动就可以了

  • input为运动开始到结束的时间值,用0表示开始的时间,1表示结束的时间,即我们上面说的时间t
  • return的值为物体所在的距离,用0表示开始的位置,1表示终点的位置,即我们上面说的y,在运动过程中,物体可能会运动到超过终点的位置后返回终点,也可能先往起点相反的位置运动后再朝终点的位置运动,也就是y∈[0,1],但y在运动过程中,可以小于0,也可以大于1

Android已提供的Interpolation:

在这里插入图片描述

LinearInterpolator

//LinearInterpolator.java
@Override
public float getInterpolation(float input) {
    return input;
}

算法 :y=t

在这里插入图片描述

结论:LinearInterpolator为匀速运动

AccelerateInterpolator

public AccelerateInterpolator() {
    mFactor = 1.0f;
    mDoubleFactor = 2.0;
}

public AccelerateInterpolator(float factor) {
    mFactor = factor;
    mDoubleFactor = 2 * mFactor;
}

factor:可以理解为运动算法效果的影响因子

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

算法 y=t^2f (f=factor)

在这里插入图片描述

结论:

  • 当factory>0.5f(factory=0.5f,为直线匀速运动)时,物体做加速运动
  • 当factory<0.5f时,物体先加速后减速运动

AccelerateDecelerateInterpolator

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

算法:y=Math.cos((t + 1) * Math.PI) / 2.0f + 0.5f

在这里插入图片描述

结论:物体运动先快后慢

DecelerateInterpolator

public DecelerateInterpolator(float factor) {
    mFactor = factor;
}
@Override
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;
}

算法:y=1-(1-t)^2f (f=factor)

在这里插入图片描述

结论:

  • 当factor>0.5f时,做减速运动
  • 当factor<0.5f时,做加速运动
  • 当factor=0.5f时,做匀速运动

AnticipateInterpolator

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

算法:y=t * t * ((tension + 1) * t - tension)

在这里插入图片描述

结论:AnticipateInterpolator为先减速向反方向运动,再加速向前运动

PathInterpolator

public PathInterpolator(Path path) {
    initPath(path);
}
@Override
public float getInterpolation(float t) {
    if (t <= 0) {
        return 0;
    } else if (t >= 1) {
        return 1;
    }
    // Do a binary search for the correct x to interpolate between.
    int startIndex = 0;
    int endIndex = mX.length - 1;

    while (endIndex - startIndex > 1) {
        int midIndex = (startIndex + endIndex) / 2;
        if (t < mX[midIndex]) {
            endIndex = midIndex;
        } else {
            startIndex = midIndex;
        }
    }

    float xRange = mX[endIndex] - mX[startIndex];
    if (xRange == 0) {
        return mY[startIndex];
    }

    float tInRange = t - mX[startIndex];
    float fraction = tInRange / xRange;

    float startY = mY[startIndex];
    float endY = mY[endIndex];
    return startY + (fraction * (endY - startY));
}

PathInterpolator是直接用path(路径)定义物体的运动规律,比如我们可以定义这样的一条path,让物体先加速到中间位置保持不动,再加速到终点。(注意path的取值是(0,0)~(1,1))

在这里插入图片描述

我们把上面的草图用Path实例化一下:

Path path=new Path();
path.moveTo(0,0);
path.quadTo(0.3f,0.3f,0.3f,0.5f);
path.lineTo(0.6f,0.5f);
path.quadTo(1f,0.5f,1f,1f);

应用到PathInterpolator:

在这里插入图片描述

结论:动画按我们给定的路径描述做运动

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

在这里插入图片描述

结论:BounceInterpolator是一种惯性弹跳的运动效果

OvershootInterpolator

public OvershootInterpolator() {
    mTension = 2.0f;
}

public OvershootInterpolator(float tension) {
    mTension = tension;
}
@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;
}

在这里插入图片描述

结论:加速超出终点后减速返回到终点 (注意tension默认的大小是2)

AnticipateOvershootInterpolator

public AnticipateOvershootInterpolator() {
    mTension = 2.0f * 1.5f;
}

public AnticipateOvershootInterpolator(float tension) {
    mTension = tension * 1.5f;
}
@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);
}

在这里插入图片描述

结论:先加速向反方向运动,再加速向前运动到路程一半后开始减速到终点,后继续向终点外运动并加速返回终点

CycleInterpolator

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

在这里插入图片描述

结论:动画按正玄曲线规律运动

LookupTableInterpolator

  • LinearOutSlowInInterpolator
  • FastOutSlowInInterpolator
  • FastOutLinearInInterpolator

这三个Interpolator继承至LookupTableInterpolator,算法是一样的,只是参数VALUES不一样,比如:

public class FastOutSlowInInterpolator extends LookupTableInterpolator {

    /**
     * Lookup table values sampled with x at regular intervals between 0 and 1 for a total of
     * 201 points.
     */
    private static final float[] VALUES = new float[] {
          ......
    };

    public FastOutSlowInInterpolator() {
        super(VALUES);
    }

}

LinearOutSlowInInterpolator

在这里插入图片描述

FastOutSlowInInterpolator

在这里插入图片描述

FastOutLinearInInterpolator

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一鱼浅游

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值