属性动画中Interpolator的使用
Android中可以通过setInterpolator()
给一个属性动画设置一个补间器,定义一个动画改变的速率,可以让一个动画做非线性的动作,比如加速或者减速,Android提供了很多功能不同的Interpolator共开发者使用,它们都是继承自TimeInterpolator
,如图:
如下代码让progressBar的进度从0变化到100,并且是先加速后减速。
valueAnimator = ValueAnimator.ofInt(0,100);
valueAnimator.setDuration(2000);
valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int p = (int) animation.getAnimatedValue();
progressBar.setProgress(p);
}
});
valueAnimator.start();
Interpolator的内部实现
先看看TimeInterpolator的源码,内部只有一个getInterpolation()
方法,方法接收一个input参数,这个参数是从0到1变化的,0代表是动画开始,1代表的是变化结束,中间的值随着动画运行在0到1之间变化,实现具体的interpolator只要实现getInterpolation()
方法,根据需要自己通过input参数去计算出interpolator就可以了。算出了这个值是怎么使用的呢,就得引出另外一个概念TypeEvaluator
/**
* 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);
}
TypeEvaluator介绍
TypeEvaluator用来计算动画如何从初始值过渡到结束值,代码很简单,只有一个计算方法,这个方法接收三个参数,fraction
,从动画开始到结束的分数,另外两个是动画开始的值和结束的值,使用这三个参数可以计算出某个时刻动画当前的值
public interface TypeEvaluator<T> {
/**
* This function returns the result of linearly interpolating the start and end values, with
* <code>fraction</code> representing the proportion between the start and end values. The
* calculation is a simple parametric calculation: <code>result = x0 + t * (x1 - x0)</code>,
* where <code>x0</code> is <code>startValue</code>, <code>x1</code> is <code>endValue</code>,
* and <code>t</code> is <code>fraction</code>.
*
* @param fraction The fraction from the starting to the ending values
* @param startValue The start value.
* @param endValue The end value.
* @return A linear interpolation between the start and end values, given the
* <code>fraction</code> parameter.
*/
public T evaluate(float fraction, T startValue, T endValue);
}
系统的ofInt
和ofFloat
动画变化对应TypeEvaluator的实现类IntEvaluator
和FloatEvaluator
看看IntEvaluator
的实现,动画结束值减去开始值算出差值,再乘以当前的动画执行分数fraction,再加上开始值就得到了当前的动画的值,我们可以通过实现TypeEvaluator
去定制自己的Evaluator,然后就可以ofObject
去使用啦
public class IntEvaluator implements TypeEvaluator<Integer> {
public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
int startInt = startValue;
return (int)(startInt + fraction * (endValue - startInt));
}
}
Interpolator和TypeEvaluator的关系
TypeEvaluator计算当前动画值所传入的fraction的值就是通过Interpolator的getInterpolator计算出来的,最简单的一种及时线性的变化,比如系统的LinearInterpolator
直接将input返回,这样fraction匀速的从0变到1,那么动画的值也就从起始值匀速的变化到结束值。
public class LinearInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {
public float getInterpolation(float input) {
return input;
}
}
再来看看AccelerateDecelerateInterpolator
代码
public class AccelerateDecelerateInterpolator implements Interpolator, NativeInterpolatorFactory {
public float getInterpolation(float input) {
return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
}
}
AccelerateDecelerateInterpolator
实现动画先加速后减速,可以看到他的算法,input从0到1,(input + 1) * Math.PI)从π到2π,cos(π~2π)变化根据三角函数是从-1 ~ 1,再除以2加上0.5刚好是0-1区间内变化,不同的是中间的变化是先加速在减速,这样就实现了动画先加速再减速的变化啦