PDF版 ePub版

# 高级进阶（一）

## 一、插值器

### 1、使用插值器

ValueAnimator animator = ValueAnimator.ofInt(0,600);

@Override
public void onAnimationUpdate(ValueAnimator animation) {
int curValue = (int)animation.getAnimatedValue();
tv.layout(tv.getLeft(),curValue,tv.getRight(),curValue+tv.getHeight());
}
});
animator.setDuration(1000);
animator.setInterpolator(new BounceInterpolator());
animator.start(); 

### 2、自定义加速器

1、概述 在这段，我们就开始着手自己写一个加速器了，在写加速器之前，先看看人家的加速器是怎么写的吧。 先看看 LinearInterpolator：

public class LinearInterpolator implements Interpolator {

public LinearInterpolator() {
}

public LinearInterpolator(Context context, AttributeSet attrs) {
}

public float getInterpolation(float input) {
return input;
}
}
public interface Interpolator extends TimeInterpolator {
}

LinearInterpolator 实现了 Interpolator 接口；而 Interpolator 接口则直接继承自 TimeInterpolator，而且并没有添加任何其它的方法。 那我们来看看 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);
}  

ValueAnimator anim = ValueAnimator.ofInt(100, 400);
anim.setDuration(1000);
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float currentValue = (float) animation.getAnimatedValue();
Log.d("TAG", "cuurent value is " + currentValue);
}
});
anim.start();  

public class LinearInterpolator implements Interpolator {

…………

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

public class MyInterploator implements TimeInterpolator {
@Override
public float getInterpolation(float input) {
return 1-input;
}
} 

ValueAnimator animator = ValueAnimator.ofInt(0,600);

@Override
public void onAnimationUpdate(ValueAnimator animation) {
int curValue = (int)animation.getAnimatedValue();
tv.layout(tv.getLeft(),curValue,tv.getRight(),curValue+tv.getHeight());
}
});
animator.setDuration(1000);
animator.setInterpolator(new MyInterploator());
animator.start(); 

## 二、Evaluator

### 1、概述

[java] view plain 当前的值 = 100 + （400 - 100）* 显示进度

### 2、各种 Evaluator

ValueAnimator animator = ValueAnimator.ofInt(0,600);

@Override
public void onAnimationUpdate(ValueAnimator animation) {
int curValue = (int)animation.getAnimatedValue();
tv.layout(tv.getLeft(),curValue,tv.getRight(),curValue+tv.getHeight());
}
});
animator.setDuration(1000);
animator.setEvaluator(new IntEvaluator());
animator.setInterpolator(new BounceInterpolator());
animator.start(); 

/**
* This evaluator can be used to perform type interpolation between <code>int</code> values.
*/
public class IntEvaluator implements TypeEvaluator<Integer> {

/**
* 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 * (v1 - v0)</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; should be of type <code>int</code> or
*                   <code>Integer</code>
* @param endValue   The end value; should be of type <code>int</code> or <code>Integer</code>
* @return A linear interpolation between the start and end values, given the
*         <code>fraction</code> parameter.
*/
public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
int startInt = startValue;
return (int)(startInt + fraction * (endValue - startInt));
}
} 

return (int)(startInt + fraction * (endValue - startInt));

当前的值 = 100 + （400 - 100）* 显示进度  

### 3、自定义 Evalutor

（1）、简单实现 MyEvalutor 前面我们看了 IntEvalutor 的代码，我们仿照 IntEvalutor 的实现方法，我们自定义一个 MyEvalutor: 首先是实现 TypeEvaluator 接口：

public class MyEvaluator implements TypeEvaluator<Integer> {
@Override
public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
return null;
}
}  

public class MyEvaluator implements TypeEvaluator<Integer> {
@Override
public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
int startInt = startValue;
return (int)(200+startInt + fraction * (endValue - startInt));
}
}  

ValueAnimator animator = ValueAnimator.ofInt(0,400);

@Override
public void onAnimationUpdate(ValueAnimator animation) {
int curValue = (int)animation.getAnimatedValue();
tv.layout(tv.getLeft(),curValue,tv.getRight(),curValue+tv.getHeight());
}
});
animator.setDuration(1000);
animator.setEvaluator(new MyEvaluator());
animator.start(); 

public class ReverseEvaluator implements TypeEvaluator<Integer> {
@Override
public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
int startInt = startValue;
return (int) (endValue - fraction * (endValue - startInt));
}
} 

ValueAnimator animator = ValueAnimator.ofInt(0,400);

@Override
public void onAnimationUpdate(ValueAnimator animation) {
int curValue = (int)animation.getAnimatedValue();
tv.layout(tv.getLeft(),curValue,tv.getRight(),curValue+tv.getHeight());
}
});
animator.setDuration(1000);
animator.setEvaluator(new ReverseEvaluator());
animator.start(); 

### 4、关于 ArgbEvalutor

1、使用 ArgbEvalutor 我们上面讲了 IntEvaluator 和 FloatEvalutor，还说了 Evalutor 一般来讲不能通用，会报强转错误，也就是说，只有在数值类型相同的情况下，Evalutor 才能共用。 其实除了 IntEvaluator 和 FloatEvalutor，在 android.animation 包下，还有另外一个 Evalutor 叫 ArgbEvalutor。 ArgbEvalutor 是用来做颜色值过渡转换的。可能是谷歌的开发人员觉得大家对颜色值变换可能并不知道要怎么做，所以特地给我们提供了这么一个过渡 Evalutor； 我们先来简单看一下 ArgbEvalutor 的源码：（这里先不做具体讲解原理，最后会讲原理，这里先会用）

public class ArgbEvaluator implements TypeEvaluator {
public Object evaluate(float fraction, Object startValue, Object endValue) {
int startInt = (Integer) startValue;
int startA = (startInt >> 24);
int startR = (startInt >> 16) & 0xff;
int startG = (startInt >> 8) & 0xff;
int startB = startInt & 0xff;

int endInt = (Integer) endValue;
int endA = (endInt >> 24);
int endR = (endInt >> 16) & 0xff;
int endG = (endInt >> 8) & 0xff;
int endB = endInt & 0xff;

return (int)((startA + (int)(fraction * (endA - startA))) << 24) |
(int)((startR + (int)(fraction * (endR - startR))) << 16) |
(int)((startG + (int)(fraction * (endG - startG))) << 8) |
(int)((startB + (int)(fraction * (endB - startB))));
}
}

ValueAnimator animator = ValueAnimator.ofInt(0xffffff00,0xff0000ff);
animator.setEvaluator(new ArgbEvaluator());
animator.setDuration(3000);

@Override
public void onAnimationUpdate(ValueAnimator animation) {
int curValue = (int)animation.getAnimatedValue();
tv.setBackgroundColor(curValue);

}
});

animator.start(); 

2、ArgbEvalutor 的实现原理 先重新看源码：

/**
* This evaluator can be used to perform type interpolation between integer
* values that represent ARGB colors.
*/
public class ArgbEvaluator implements TypeEvaluator {

/**
* This function returns the calculated in-between value for a color
* given integers that represent the start and end values in the four
* bytes of the 32-bit int. Each channel is separately linearly interpolated
* and the resulting calculated values are recombined into the return value.
*
* @param fraction The fraction from the starting to the ending values
* @param startValue A 32-bit int value representing colors in the
* separate bytes of the parameter
* @param endValue A 32-bit int value representing colors in the
* separate bytes of the parameter
* @return A value that is calculated to be the linearly interpolated
* result, derived by separating the start and end values into separate
* color channels and interpolating each one separately, recombining the
* resulting values in the same way.
*/
public Object evaluate(float fraction, Object startValue, Object endValue) {
int startInt = (Integer) startValue;
int startA = (startInt >> 24);
int startR = (startInt >> 16) & 0xff;
int startG = (startInt >> 8) & 0xff;
int startB = startInt & 0xff;

int endInt = (Integer) endValue;
int endA = (endInt >> 24);
int endR = (endInt >> 16) & 0xff;
int endG = (endInt >> 8) & 0xff;
int endB = endInt & 0xff;

return (int)((startA + (int)(fraction * (endA - startA))) << 24) |
(int)((startR + (int)(fraction * (endR - startR))) << 16) |
(int)((startG + (int)(fraction * (endG - startG))) << 8) |
(int)((startB + (int)(fraction * (endB - startB))));
}
}  

int startInt = (Integer) startValue;
int startA = (startInt >> 24);
int startR = (startInt >> 16) & 0xff;
int startG = (startInt >> 8) & 0xff;
int startB = startInt & 0xff;

int endInt = (Integer) endValue;
int endA = (endInt >> 24);
int endR = (endInt >> 16) & 0xff;
int endG = (endInt >> 8) & 0xff;
int endB = endInt & 0xff;  

startA + (int)(fraction * (endA - startA)))