Android 属性动画 Evaluator

我们知道创建 ValueAnimator 实例的方法是调用 ValueAnimatorofInt()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


  1. 创建一个 空的 Android 项目 cn.twle.android.EvaluatorCustom

  2. 创建一个 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;
        }
    }
    
  3. 创建自定义 EvaluatorPointEvaluator.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;
        }
    }
    
  4. 创建一个自定义 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);
            }
        }
    }
    
  5. 修改 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 来控制颜色


  1. 复用上面的范例

  2. 创建一个颜色 EvaluatorColorEvaluator.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);
        }
    }
    
  3. 然后创建另一个 ViewAnimView2.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();
        }
    }
    
  4. 修改 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));
        }
    }
    

Android 基础教程

关于   |   FAQ   |   我们的愿景   |   广告投放   |  博客

  简单教程,简单编程 - IT 入门首选站

Copyright © 2013-2022 简单教程 twle.cn All Rights Reserved.