Android 属性动画 Evaluator
我们知道创建 ValueAnimator
实例的方法是调用 ValueAnimator
的 ofInt()
, ofFloat()
或 ofObject()
静态方法
ofInt()
和 ofFloat()
前面我们都学会了,分别用于对浮点型和整型的数据进行动画操作
那么 ofObject()
呢?
初始对象和结束对象?如何过渡法?或者说这玩意怎么用?
好的,带着疑问,我们先来了解一个东西:Evaluator
Evaluator
Evaluator (计算器) 用于高速动画系统如何从初始值过渡到结束值
Android 提供了以下几种 Evaluator
Evaluator | 说明 |
---|---|
IntEvaluator | 用于计算 int 类型属性值的计算器 |
FloatEvaluator | 用于计算 float 类型属性值的计算器 |
ArgbEvaluator | 用于计算十六进制形式表示的颜色值的计算器 |
TypeEvaluator | 计算器的接口,我们可以实现该接口来完成自定义计算器 |
我们先来看看 IntEvaluator
的源码
package android.animation; public class IntEvaluator implements TypeEvaluator<Integer> { public Integer evaluate(float fraction, Integer startValue, Integer endValue) { int startInt = startValue; return (int)(startInt + fraction * (endValue - startInt)); } }
实现了 TypeEvaluator 接口,然后重写了 evaluate() 方法,参数有三个,依次是:
参数 | 说明 |
---|---|
fraction | 动画的完成度,可以根据它来计算动画的值应该是多少 |
startValue | 动画的起始值 |
endValue | 动画的结束值 |
动画的值 = 初始值 + 完成度 * (结束值 - 初始值)
如果我们想告诉系统如何从初始对象过度到结束对象,那么我们就要自己来实现 TypeEvaluator 接口,即自定义 Evaluator
范例
我们写一个范例来实现自定义 Evaluator
-
创建一个 空的 Android 项目
cn.twle.android.EvaluatorCustom
-
创建一个
Point.java
用来表示一个点package cn.twle.android.evaluatorcustom; public class Point { private float x; private float y; public Point() { } public Point(float x, float y) { this.x = x; this.y = y; } public float getX() { return x; } public float getY() { return y; } public void setX(float x) { this.x = x; } public void setY(float y) { this.y = y; } }
-
创建自定义
Evaluator
类 PointEvaluator.java 实现接口重写evaluate()
方法package cn.twle.android.evaluatorcustom; import android.animation.TypeEvaluator; public class PointEvaluator implements TypeEvaluator<Point>{ @Override public Point evaluate(float fraction, Point startValue, Point endValue) { float x = startValue.getX() + fraction * (endValue.getX() - startValue.getX()); float y = startValue.getY() + fraction * (endValue.getY() - startValue.getY()); Point point = new Point(x, y); return point; } }
-
创建一个自定义 View 类
AnimView.java
package cn.twle.android.evaluatorcustom; import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.util.AttributeSet; import android.view.View; public class AnimView extends View { public static final float RADIUS = 80.0f; private Point currentPoint; private Paint mPaint; public AnimView(Context context) { this(context, null); } public AnimView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public AnimView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } private void init() { mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mPaint.setColor(Color.BLUE); } private void drawCircle(Canvas canvas){ float x = currentPoint.getX(); float y = currentPoint.getY(); canvas.drawCircle(x, y, RADIUS, mPaint); } private void startAnimation() { Point startPoint = new Point(RADIUS, RADIUS); Point endPoint = new Point(getWidth() - RADIUS, getHeight() - RADIUS); ValueAnimator anim = ValueAnimator.ofObject(new PointEvaluator(), startPoint, endPoint); anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { currentPoint = (Point) animation.getAnimatedValue(); invalidate(); } }); anim.setDuration(3000l); anim.start(); } @Override protected void onDraw(Canvas canvas) { if (currentPoint == null) { currentPoint = new Point(RADIUS, RADIUS); drawCircle(canvas); startAnimation(); } else { drawCircle(canvas); } } }
-
修改
MainActivity.java
实例化AnimView
package cn.twle.android.evaluatorcustom; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(new AnimView(this)); } }
增强版
我们给上面的范例加上颜色的变化
我们另外用一个 ObjectAnimator
来加载颜色变化的动画,在 View
中加多个 int color
来控制颜色
-
复用上面的范例
-
创建一个颜色
Evaluator
类ColorEvaluator.java
package cn.twle.android.evaluatorcustom; import android.animation.TypeEvaluator; import android.graphics.Color; public class ColorEvaluator implements TypeEvaluator<Integer>{ @Override public Integer evaluate(float fraction, Integer startValue, Integer endValue) { int alpha = (int) (Color.alpha(startValue) + fraction * (Color.alpha(endValue) - Color.alpha(startValue))); int red = (int) (Color.red(startValue) + fraction * (Color.red(endValue) - Color.red(startValue))); int green = (int) (Color.green(startValue) + fraction * (Color.green(endValue) - Color.green(startValue))); int blue = (int) (Color.blue(startValue) + fraction * (Color.blue(endValue) - Color.blue(startValue))); return Color.argb(alpha, red, green, blue); } }
-
然后创建另一个
View
类AnimView2.java
package cn.twle.android.evaluatorcustom; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.util.AttributeSet; import android.view.View; public class AnimView2 extends View { public static final float RADIUS = 80.0f; private Point currentPoint; private Paint mPaint; private int mColor; public AnimView2(Context context) { this(context, null); } public AnimView2(Context context, AttributeSet attrs) { super(context, attrs); init(); } public AnimView2(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } private void init() { mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mPaint.setColor(Color.BLUE); } private void drawCircle(Canvas canvas){ float x = currentPoint.getX(); float y = currentPoint.getY(); canvas.drawCircle(x, y, RADIUS, mPaint); } private void startAnimation() { Point startPoint = new Point(RADIUS, RADIUS); Point endPoint = new Point(getWidth() - RADIUS, getHeight() - RADIUS); ValueAnimator anim = ValueAnimator.ofObject(new PointEvaluator(), startPoint, endPoint); anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { currentPoint = (Point) animation.getAnimatedValue(); invalidate(); } }); ObjectAnimator objectAnimator = ObjectAnimator.ofObject(this, "color", new ColorEvaluator(), Color.BLUE, Color.RED); //动画集合将前面两个动画加到一起,with同时播放 AnimatorSet animatorSet = new AnimatorSet(); animatorSet.play(anim).with(objectAnimator); animatorSet.setStartDelay(1000l); animatorSet.setDuration(3000l); animatorSet.start(); } @Override protected void onDraw(Canvas canvas) { if (currentPoint == null) { currentPoint = new Point(RADIUS, RADIUS); drawCircle(canvas); startAnimation(); } else { drawCircle(canvas); } } //color的get和set方法~ public int getColor() { return mColor; } public void setColor(int color) { mColor = color; mPaint.setColor(color); invalidate(); } }
-
修改
MainActivity.java
实例化AnimView2
package cn.twle.android.evaluatorcustom; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(new AnimView2(this)); } }