自定义插值器与Evaluator

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自定义插值器与Evaluator相关的知识,希望对你有一定的参考价值。


  • 在视图动画中仅仅允许我们使用setInterpolator()函数来设置插值器,但是对于Animator来说,不仅可以设置插值器,还可以设置Evalator(差值器)
  • 比如刚才我们定义的ofInt(0,400)那么他的移动速度是通过什么来设置的呢,插值器就是用来控制动画的区间值如何被计算出来的
  • 系统自带的匀速插值器:
public class LinearInterpolator implements Interpolator
public LinearInterpolator()

public LinearInterpolator(Context context, AttributeSet attrs0

public float getInterpolation(float input)
return input;


//实现了Interpolator接口, 继承了TimeInterpolator
public interface Interpolator extends TimeInterpolator
  • TimeInterpolator:
public interface TImeInterpolator
//input表示当前动画的进度。取0时表示动画开始,取1时表示动画结束
//返回值表示当前想要显示的进度,超过1表示已经超过目标值,小于0表示小于开始位置
//动画随着设定的时长均匀增加,返回值的对应的是使用ofInt()还是ofFloat()
float getInterpolation(float input);
  • 理解ofInt():
ofint(100,400);
curValue = 100 + (400-100)*进度
所以说现实的进度就是当前的位置
注意:input的值与设定的距离没有任何关系,只与时间有关,随着时间的推移进度也就自然的增加,input参数表示来了当前的动画的进度,返回值表示当前的动画的数值进度。
插值器进度源码:
  • LinearInterpolator 匀速:
public class LinearInterpolator implements Interpolator
public float getInterpolator(float input)
return input;


//发现直接将input返回,也就是说时间和进度是同步变化的,多以就是匀速变化
  • AccelerateDecelerateInterpolator 先加速后减速:
public float getInterpolation(float input)     
return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
  • AccelerateInterpolator 加速后立即停止:
public float getInterpolation(float input)     
if (mFactor == 1.0f)
return input * input;
else

return (float)Math.pow(input, mDoubleFactor);

  • 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;
  • 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;
  • AnticipateInterpolator 反向初始:
public float getInterpolation(float t)     
// a(t) = t * t * ((tension + 1) * t - tension)
return t * t * ((mTension + 1) * t - mTension);
  • 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;
  • 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);
  • CycleInterpolator 循环插值器 :
public float getInterpolation(float input)     
return (float)(Math.sin(2 * mCycles * Math.PI * input));
  • 看了上述的插值器的getInterpolator函数后, 自定义一个插值器:
public class MyInterpolator implements TimeInterpolator     
@Override
public float getInterpolation(float input)
//反向插值器
return 1-input;

  • Evaluator:
  • 数值转换器,负责将插值器返回的小数表示的进度的,转化为数值表示的位置
  • ofInt()对应IntEvaluator, ofFloat()对应FloatEvaluator
  • ofInt()和ofFloat()都有系统默认的Evaluator和Interpolator供使用,分别默认的就是上述的两个函数
  • 来看一下IntEvaluator的源码实现:
public class IntEvaluator implements TypeEvaluator<Integer>      
//fraction就是其中的插值器的返回值,表示当前动画的数值进度,百分小数表示
//startValue和endValue分别表示ofInt()中的两个参数,
//返回值就是curValue的具体的数值
//计算方式:eg: 100 + (400-100)*进度
public Integer evaluate(float fraction, Integer startValue, Integer endValue)
int startInt = startValue;
return (int)(startInt + fraction * (endValue - startInt));

  • 实现一个Evaluator:
public class MyEvaluator implements TypeEvaluator<Integer>     
@Override
public Integer evaluate(float fraction, Integer startValue, Integer endValue)
int startInt = startValue;
//在实际的基础上加200
return (int)(200 + startInt + fraction*(endValue-startInt));

总结:我们既可以 通过重写插值器的getInterpolator()函数来改变数值及进度的位置,也可以通过重写evaluate()函数来改变数值位置
  • 反向动画(上述通过getInterpolatotr实现):
public class ReserveEvaluator implements TypeEvaluator<Integer>     
@Override
public Integer evaluate(float fraction, Integer startValue, Integer endValue)
int startInt = startValue;
//实现反向动画
return (int)(endValue - fraction * (endValue-startInt));


以上是关于自定义插值器与Evaluator的主要内容,如果未能解决你的问题,请参考以下文章

android.animation - ValueAnimator的 Interpolator 和 Evaluator

图像处理复习整理(3.图像差值)

Android属性动画:插值器与估值器

差值的再议-Hermite差值

「Scipy」样条插值在数据可视化中的运用

delimiters 插值 选项