Android动画系列:
- 补间动画详解
- 帧动画
- LayoutAnimation
- LayoutTransition
- 属性动画 - 基本使用
- 属性动画 - Interpolator(内插器)
- 属性动画 - TypeEvaluator
- 属性动画 - Keyframe
- AnimatorSet
对于Evaluators,即属性动画计算器,官方根据实际需求已经为我们实现了几种,但在实际开发过程中,官方定义的那几种并不能满足我们实际的需求,比如在背景变色的同时将控件移动并缩小,有的人说可以使用AnimatorSet实现,当然能AnimatorSet可以轻易实现,假如我们就用一个ValueAnimator该怎么实现呢?
之前有提到过TypeEvaluator这个接口,其用来实现自定义动画属性值的计算器。TypeEvaluator接口中只定义了一个方法,evaluate(float fraction, T startValue, T endValue),evaluate可以接受三个参数fraction,startValue,endValue,其中startValue和endValue都是使用泛型定义的,意味着我们可以自定义传入的计算的动画属性,其返回值也使我们定义的的动画属性类型,以达到在AnimatorUpdateListener监听中,计算出来的属性值都是我们定义的。
TypeEvaluator的实现类一般与 setEvaluator(TypeEvaluator)方法或者ofObject(TypeEvaluator, Object… values)配合使用,来定义动画的属性值计算器。
- fraction : 动画进度
- startValue T : 动画属性初始值
- endValue T: 动画属性结束值
自定义TypeEvaluator
首先,定一个动画相关属性的类MyPoint,其内包含了trance、color、scale等三个动画相关的属性。
public class MyPoint {
float trance; // 移动距离
int color; // 颜色
float scale; // 缩放比例
****
}
接下来,我们自定义一个Evaluator类,命名为MyEvaluator,其实现了接口TypeEvaluator,并将刚才定义的MyPoint作为动画的属性值类型。在evaluate()方法中,根据动画的执行进度,对trance、color、scale等三个属性分别做了相应处理。
public class MyEvaluator implements TypeEvaluator<MyPoint> {
@Override
public MyPoint evaluate(float fraction, MyPoint pointStart, MyPoint pointEnd) {
MyPoint pointCurrent = new MyPoint();
pointCurrent.setColor(getCurrentColor(fraction, pointStart.getColor(), pointEnd.getColor()));
pointCurrent.setTrance(getCurrentTrance(fraction, pointStart.getTrance(), pointEnd.getTrance()));
pointCurrent.setScale(getCurrentScale(fraction, pointStart.getScale(), pointEnd.getScale()));
return pointCurrent;
}
/**
* 根据fraction值来计算当前的颜色。
*/
private int getCurrentColor(float fraction, int startColor, int endColor) {
int redCurrent;
int blueCurrent;
int greenCurrent;
int alphaCurrent;
int redStart = Color.red(startColor);
int blueStart = Color.blue(startColor);
int greenStart = Color.green(startColor);
int alphaStart = Color.alpha(startColor);
int redEnd = Color.red(endColor);
int blueEnd = Color.blue(endColor);
int greenEnd = Color.green(endColor);
int alphaEnd = Color.alpha(endColor);
int redDifference = redEnd - redStart;
int blueDifference = blueEnd - blueStart;
int greenDifference = greenEnd - greenStart;
int alphaDifference = alphaEnd - alphaStart;
redCurrent = (int) (redStart + fraction * redDifference);
blueCurrent = (int) (blueStart + fraction * blueDifference);
greenCurrent = (int) (greenStart + fraction * greenDifference);
alphaCurrent = (int) (alphaStart + fraction * alphaDifference);
return Color.argb(alphaCurrent, redCurrent, greenCurrent, blueCurrent);
}
/**
* 根据fraction值来计算当前的移动距离
*/
private float getCurrentTrance(float fraction, float tranceStart, float tranceEnd) {
float tranceCurrent;
float difference;
difference = tranceEnd - tranceStart;
tranceCurrent = tranceStart + difference * fraction;
return tranceCurrent;
}
/**
* 根据fraction值来计算当前缩放比例
*/
private float getCurrentScale(float fraction, float scaleStart, float scaleEnd) {
float scaleCurrent;
float difference;
difference = scaleEnd - scaleStart;
scaleCurrent = scaleStart + difference * fraction;
return scaleCurrent;
}
}
最后使用静态方法ofObject(TypeEvaluator, T…values)创建ValueAnimator对象valueAnimator,通过系列setXX()方法,对valueAnimator做动画的相应设置,在AnimatorUpdateListener监听的onAnimationUpdate(ValueAnimator)方法中,通过getAnimatedValue()可以获得当前的动画的属性值,其类型强转为MyPoint,再设定View的相关属性,以达到动画效果。
//起始颜色为红色
int startColor = 0xffff0000;
//终止颜色为绿色
int endColor = 0xff00ff00;
MyPoint pointStart = new MyPoint(0f, startColor, 1.0f);
MyPoint pointEnd = new MyPoint(400f, endColor, 0.2f);
// 通过静态方法构建一个ValueAnimator对象
// 动画属性值计算器使用自定义的计算器(MyEvaluator)
ValueAnimator valueAnimator = ValueAnimator.ofObject(new MyEvaluator(), pointStart, pointEnd);
// 设置作用对象
valueAnimator.setTarget(btnProperty);
// 设置动画无限循环
valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
// 设置动画执行时间
valueAnimator.setDuration(4000);
// 添加动画更新监听
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
// 获取当前值
MyPoint mValue = (MyPoint) animation.getAnimatedValue();
// 动画进度(t/duration)
float fraction = animation.getAnimatedFraction();
Log.d("PropertyActivity", "mValue:" + mValue.toString());
Log.d("PropertyActivity", "fraction:" + fraction + " | t:" + fraction * animation.getDuration());
// 设置横向偏移量
btnProperty.setTranslationX(mValue.getTrance() * 0.5f);
// 设置纵向偏移量
btnProperty.setTranslationY(mValue.getTrance());
// 设置背景颜色
btnProperty.setBackgroundColor(mValue.getColor());
// 设置横向缩放
btnProperty.setScaleX(mValue.getScale());
// 设置纵向缩放
btnProperty.setScaleX(mValue.getScale());
}
});
valueAnimator.start();