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