NineOldAndroidsDemos 学习(9) CustomEvaluator

本文介绍了一种使用自定义评估器实现复杂动画效果的方法。通过创建`XYEvaluator`类实现`TypeEvaluator`接口,可以计算任意时间点上的位置,从而实现非线性的动画变化。此外,还提供了一个具体的例子——`MyAnimationView`类,该类演示了如何使用自定义评估器创建一个沿特定路径移动的小球动画。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

public class CustomEvaluator extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.animator_custom_evaluator);
        LinearLayout container = (LinearLayout) findViewById(R.id.container);
        final MyAnimationView animView = new MyAnimationView(this);
        container.addView(animView);

        Button starter = (Button) findViewById(R.id.startButton);
        starter.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                animView.startAnimation();
            }
        });
    }

    public class XYHolder {
        private float mX;
        private float mY;

        public XYHolder(float x, float y) {
            mX = x;
            mY = y;
        }

        public float getX() {
            return mX;
        }

        public void setX(float x) {
            mX = x;
        }

        public float getY() {
            return mY;
        }

        public void setY(float y) {
            mY = y;
        }
    }

    public class XYEvaluator implements TypeEvaluator {
        public Object evaluate(float fraction, Object startValue, Object endValue) { //你可以自己计算在某个时间点的位置
            XYHolder startXY = (XYHolder) startValue;                                //这里做的是匀速直线运动
            XYHolder endXY = (XYHolder) endValue;
            return new XYHolder(startXY.getX() + fraction * (endXY.getX() - startXY.getX()),
                    startXY.getY() + fraction * (endXY.getY() - startXY.getY()));
        }
    }

    public class BallXYHolder {

        private ShapeHolder mBall;

        public BallXYHolder(ShapeHolder ball) {
            mBall = ball;
        }

        public void setXY(XYHolder xyHolder) {
            mBall.setX(xyHolder.getX());
            mBall.setY(xyHolder.getY());
        }

        public XYHolder getXY() {
            return new XYHolder(mBall.getX(), mBall.getY());
        }
    }

    public class MyAnimationView extends View implements ValueAnimator.AnimatorUpdateListener {

        public final ArrayList<ShapeHolder> balls = new ArrayList<ShapeHolder>();
        ValueAnimator bounceAnim = null;
        ShapeHolder ball = null;
        BallXYHolder ballHolder = null;

        public MyAnimationView(Context context) {
            super(context);
            ball = createBall(25, 25);
            ballHolder = new BallXYHolder(ball);
        }

        private void createAnimation() {
            if (bounceAnim == null) {
                XYHolder startXY = new XYHolder(30f, 100f);//动画开始点
                XYHolder midXY = new XYHolder(300f, 700f); //中间点
                XYHolder endXY = new XYHolder(400f, 500f);//结束点
                // 在这里 xY对于的是 BallXYHolder 对象的getXY 和setXY ,这里有个地方需要注意get 和set 的第一个
                //字母会被转化为大写 所以xY 和XY 都可以实现 动画 但是 xy 和Xy 对应的却是   getXy 和 setXy 故不
                //能实现动画会报方法不能找到的错误.
                
                //这里的执行顺序是这样的
                //1. 读取startXY midXY endXY
                //2. 通过XYEvaluator的 evaluate 计算当前帧 的 位置
                //3. 读取 返回的XYHolder 通过 BallXYHolder 的setXY 来这是小球的位置
                bounceAnim = ObjectAnimator.ofObject(ballHolder, "xY", 
                        new XYEvaluator(), startXY, midXY ,endXY); //values参数可以随便设置几个设几个
                bounceAnim.setDuration(1500);
                bounceAnim.addUpdateListener(this);
            }
        }

        public void startAnimation() {
            createAnimation();
            bounceAnim.start();
        }

        private ShapeHolder createBall(float x, float y) {
            OvalShape circle = new OvalShape();
            circle.resize(50f, 50f);
            ShapeDrawable drawable = new ShapeDrawable(circle);
            ShapeHolder shapeHolder = new ShapeHolder(drawable);
            shapeHolder.setX(x - 25f);
            shapeHolder.setY(y - 25f);
            int red = (int)(Math.random() * 255);
            int green = (int)(Math.random() * 255);
            int blue = (int)(Math.random() * 255);
            int color = 0xff000000 | red << 16 | green << 8 | blue;
            Paint paint = drawable.getPaint(); //new Paint(Paint.ANTI_ALIAS_FLAG);
            int darkColor = 0xff000000 | red/4 << 16 | green/4 << 8 | blue/4;
            RadialGradient gradient = new RadialGradient(37.5f, 12.5f,
                    50f, color, darkColor, Shader.TileMode.CLAMP);
            paint.setShader(gradient);
            shapeHolder.setPaint(paint);
            return shapeHolder;
        }

        @Override
        protected void onDraw(Canvas canvas) {
            canvas.save();
            canvas.translate(ball.getX(), ball.getY());
            ball.getShape().draw(canvas);
            canvas.restore();
        }

        public void onAnimationUpdate(ValueAnimator animation) {
            invalidate();
        }

    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值