属性动画估值器
补间动画只能对View进行操作,属性动画不受限制,那么值的变化就用到了估值器
evaluator[ɪ'væljʊeɪtə(r)] 估值器
1、TypeEvaluator
告诉系统动画如何从初始值过渡到结束值,大多情况使用系统提供的估值器。ValueAnimator.ofFloat就使用了如下估值器:
public class FloatEvaluator implements TypeEvaluator {
public Object evaluate(float fraction, Object startValue, Object endValue) {
float startFloat = ((Number) startValue).floatValue();
return startFloat + fraction * (((Number) endValue).floatValue() - startFloat);
}
}
对于系统无法提供的,那么就要自己实现TypeEvaludator实现估值器
2、估值器的应用
ObjectAnimator本质对属性的更改,实际使用了ValueAnimator.ofObject操作对象,下面需要刷新页面使用了ofObject
两个自定义的估值器
public class PointEvaluator implements TypeEvaluator{
@Override
public Object evaluate(float fraction, Object startValue, Object endValue) {
PointF startPoint = (PointF) startValue;
PointF endPoint = (PointF) endValue;
float x = startPoint.x + fraction * (endPoint.x - startPoint.x);
float y = startPoint.y + fraction * (endPoint.y - startPoint.y);
PointF point = new PointF(x, y);
return point;
}
}
public class ColorEvaluator implements TypeEvaluator {
private int mCurrentRed = -1;
private int mCurrentGreen = -1;
private int mCurrentBlue = -1;
@Override
public Object evaluate(float fraction, Object startValue, Object endValue) {
String startColor = (String) startValue;
String endColor = (String) endValue;
int startRed = Integer.parseInt(startColor.substring(1, 3), 16);
int startGreen = Integer.parseInt(startColor.substring(3, 5), 16);
int startBlue = Integer.parseInt(startColor.substring(5, 7), 16);
int endRed = Integer.parseInt(endColor.substring(1, 3), 16);
int endGreen = Integer.parseInt(endColor.substring(3, 5), 16);
int endBlue = Integer.parseInt(endColor.substring(5, 7), 16);
// 初始化颜色的值
if (mCurrentRed == -1) {
mCurrentRed = startRed;
}
if (mCurrentGreen == -1) {
mCurrentGreen = startGreen;
}
if (mCurrentBlue == -1) {
mCurrentBlue = startBlue;
}
// 计算初始颜色和结束颜色之间的差值
int redDiff = Math.abs(startRed - endRed);
int greenDiff = Math.abs(startGreen - endGreen);
int blueDiff = Math.abs(startBlue - endBlue);
int colorDiff = redDiff + greenDiff + blueDiff;
if (mCurrentRed != endRed) {
mCurrentRed = getCurrentColor(startRed, endRed, colorDiff, 0,
fraction);
} else if (mCurrentGreen != endGreen) {
mCurrentGreen = getCurrentColor(startGreen, endGreen, colorDiff,
redDiff, fraction);
} else if (mCurrentBlue != endBlue) {
mCurrentBlue = getCurrentColor(startBlue, endBlue, colorDiff,
redDiff + greenDiff, fraction);
}
// 将计算出的当前颜色的值组装返回
String currentColor = "#" + getHexString(mCurrentRed)
+ getHexString(mCurrentGreen) + getHexString(mCurrentBlue);
return currentColor;
}
/**
* 根据fraction值来计算当前的颜色。
*/
private int getCurrentColor(int startColor, int endColor, int colorDiff,
int offset, float fraction) {
int currentColor;
if (startColor > endColor) {
currentColor = (int) (startColor - (fraction * colorDiff - offset));
if (currentColor < endColor) {
currentColor = endColor;
}
} else {
currentColor = (int) (startColor + (fraction * colorDiff - offset));
if (currentColor > endColor) {
currentColor = endColor;
}
}
return currentColor;
}
/**
* 将10进制颜色值转换成16进制。
*/
private String getHexString(int value) {
String hexString = Integer.toHexString(value);
if (hexString.length() == 1) {
hexString = "0" + hexString;
}
return hexString;
}
}
View中绘制并使用动画
public class AnimView extends View {
public static final float radius = 50f;
private PointF currentPoint;
private Paint mPaint;
private String color;
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public AnimView(Context context, AttributeSet attrs) {
super(context, attrs);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.BLUE);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if(currentPoint == null){
currentPoint = new PointF(radius, radius);
drawCircle(canvas);
startAnimator();
}else{
drawCircle(canvas);
}
}
private void drawCircle(Canvas canvas){
float x = currentPoint.x;
float y = currentPoint.y;
canvas.drawCircle(x, y, radius, mPaint);
}
private void startAnimator(){
PointF startPoint = new PointF(radius, radius);
PointF endPoint = new PointF(getWidth() - radius, getHeight() - radius);
ValueAnimator anim = ValueAnimator.ofObject(new PointEvaluator(), startPoint, endPoint);
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener(){
@Override
public void onAnimationUpdate(ValueAnimator animation) {
currentPoint = (PointF) animation.getAnimatedValue();
invalidate();
}
});
ObjectAnimator anim2 = ObjectAnimator.ofObject(this, "color", new ColorEvaluator(),
"#0000FF", "#FF0000");
AnimatorSet animSet = new AnimatorSet();
animSet.play(anim).with(anim2);
animSet.setDuration(5000);
animSet.start();
}
}
XML中直接使用
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<me.zcy.animatortest.AnimView
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
浙公网安备 33010602011771号