zoukankan      html  css  js  c++  java
  • Android 利用属ObjectAnimator,AnimatorSet性动画绘制一个弹球,加速下落,到底部时挤压,然后减速上弹

    属性动画主要的几个类介绍:

    1.ValueAnimator:这个类提供了一个简单的计时引擎运行动画动画计算值和设置目标对象。注意:使用该类时一般都是用:ObjectAnimator,而基于ObjectAnimator执行的属性动画,都是根据java的反射机制来设置的,因此设置动画的目标对象的属性必须有getter 和setter方法。

      setDuration:设置动画的时间

      setInterpolator:设置一个插入器,例如:减速器(DecelerateInterpolator),加速器(AccelerateInterpolator),当然也可以自定义,自定义时只需要继承这两个类就行了,这里就不做讨论了。

      setEvaluator:设置评估者

        1.ArgbEvaluator:这种评估者可以用来执行类型之间的插值整数值代表ARGB颜色。

        2.FloatEvaluator:这种评估者可以用来执行浮点值之间的插值。
        3.IntEvaluator:这种评估者可以用来执行类型int值之间的插值。
        4.RectEvaluator:这种评估者可以用来执行类型之间的插值矩形值。

      setRepeatCount:设置动画的重复次数(是一个int类型的值)

      setRepeatMode:设置动画模式

      start:启动动画

    2.AnimatorSet:这个类为一组特定的动画指定顺序。

      总要方法如下:

      play:该方法创建一个构造器对象用于创建约束。

      playTogether:设置同时运行一组动画

      pase:暂停一个正在运行的动画

      resume:重新运行暂停后的动画

      isRunning:判断动画是否正在运行

      isStarted:判断动画是否已经运行了

      start:开始动画

    3.AnimatorSet.Builder创建一个用于约束动画的建造器

      after(Animator):执行前面的动画后执行该动画

      after(long delay):延迟n毫秒之后执行动画

      before(Animator):执行前面动画前执行动画

      with(Animator):和前面动画一块执行

    4.ShapeDrawable:模型drawable,创建时需要传入一个图形模型

    以下是一个简单的Demo例子用于测试以上情况(小球加速下落挤压后减速上弹)

    一、BackgroundView.java

    package cn.yw.lib.animation;
    
    import android.animation.AnimatorSet;
    import android.animation.ArgbEvaluator;
    import android.animation.ObjectAnimator;
    import android.animation.ValueAnimator;
    import android.annotation.SuppressLint;
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.RadialGradient;
    import android.graphics.Shader;
    import android.graphics.drawable.ShapeDrawable;
    import android.graphics.drawable.shapes.OvalShape;
    import android.view.MotionEvent;
    import android.view.SurfaceHolder;
    import android.view.SurfaceView;
    import android.view.animation.AccelerateInterpolator;
    import android.view.animation.DecelerateInterpolator;
    
    /**
     * 属性动画,背景轮询切换
     * 为什么要使用SurfaceView而不是用View:
     *     1.这里稍作解释,由于SurfaceView继承了View,绘制起来和SurfaceView没有太大的区别,
     *  2.SurfaceView本身自带双缓冲技术,能够更好的支持动画操作
     * 
     * 
     * @author yw-tony
     * 
     */
    @SuppressLint("NewApi")
    public class BackgroundView extends SurfaceView implements
            SurfaceHolder.Callback, Runnable {
        
        private SurfaceHolder holder;
        private ShapeHolder shapHolder;
    
        public BackgroundView(Context context) {
            super(context);
            this.holder = this.getHolder();
            this.holder.addCallback(this);
        }
    
        /**
         * 创建一个小球
         */
        private void createABall(float x, float y) {
            OvalShape oval = new OvalShape();
            //设置拓原模型的宽高都为50f,即模型为原型
            oval.resize(50f, 50f);
            //创建一个模型drawable
            ShapeDrawable drawable = new ShapeDrawable(oval);
            shapHolder = new ShapeHolder(drawable);
            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);
            shapHolder.setPaint(paint);
            //设置小球的初始位置
            shapHolder.setX(x);
            shapHolder.setY(y);
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            if (event.getAction() != MotionEvent.ACTION_DOWN
                    && event.getAction() != MotionEvent.ACTION_MOVE) {
                return false;
            }
            //创建一个小球
            createABall(event.getX(), event.getY());
            //设置动画的Y轴活动范围
            float startY = shapHolder.getY();
            float endY = getHeight() - 50f;
            // int duration = (int)(500 * ((h - eventY)/h));
            // 小球弹跳动画的时间为500毫秒
            int duration = 500;
            ValueAnimator bounceAnim = ObjectAnimator.ofFloat(shapHolder, "y",
                    startY, endY);
            bounceAnim.setDuration(duration);
            // 加速器,小球会加速下落
            bounceAnim.setInterpolator(new AccelerateInterpolator());
            // 以下几个是挤压动画
            
            ValueAnimator squashAnim1 = ObjectAnimator.ofFloat(shapHolder, "x",
                    ////设置x周的动画范围
                    shapHolder.getX(), shapHolder.getX() - 25f);
            //设置压缩动画时间为下落动画时间的四分之一
            squashAnim1.setDuration(duration / 4);
            squashAnim1.setRepeatCount(1);
            squashAnim1.setRepeatMode(ValueAnimator.REVERSE);
            //挤压是做减速运动
            squashAnim1.setInterpolator(new DecelerateInterpolator());
            ValueAnimator squashAnim2 = ObjectAnimator.ofFloat(shapHolder, "width",
                    //设置小球宽度动画
                    shapHolder.getWidth(), shapHolder.getWidth() + 50);
            squashAnim2.setDuration(duration / 4);
            squashAnim2.setRepeatCount(1);
            squashAnim2.setRepeatMode(ValueAnimator.REVERSE);
            //小球做减速运动
            squashAnim2.setInterpolator(new DecelerateInterpolator());
            //设置伸展动画
            ValueAnimator stretchAnim1 = ObjectAnimator.ofFloat(shapHolder, "y",
                    endY, endY + 25f);
            stretchAnim1.setDuration(duration / 4);
            stretchAnim1.setRepeatCount(1);
            
            stretchAnim1.setInterpolator(new DecelerateInterpolator());
            stretchAnim1.setRepeatMode(ValueAnimator.REVERSE);
            ValueAnimator stretchAnim2 = ObjectAnimator.ofFloat(shapHolder,
                    "height", shapHolder.getHeight(), shapHolder.getHeight() - 25);
            stretchAnim2.setDuration(duration / 4);
            stretchAnim2.setRepeatCount(1);
            stretchAnim2.setInterpolator(new DecelerateInterpolator());
            stretchAnim2.setRepeatMode(ValueAnimator.REVERSE);
    
            ValueAnimator bounceBackAnim = ObjectAnimator.ofFloat(shapHolder, "y",
                    endY, startY);
            bounceBackAnim.setDuration(duration);
            // 减速器
            bounceBackAnim.setInterpolator(new DecelerateInterpolator());
            
            //设置动画对象的顺序
            AnimatorSet bouncer = new AnimatorSet();
            //先加速下落然后再执行挤压动画1
            bouncer.play(bounceAnim).before(squashAnim1);
            //播放挤压动画1的同事播放挤压动画2
            bouncer.play(squashAnim1).with(squashAnim2);
            bouncer.play(squashAnim1).with(stretchAnim1);
            bouncer.play(squashAnim1).with(stretchAnim2);
            //执行完挤压动画后执行小球弹起动画
            bouncer.play(bounceBackAnim).after(stretchAnim2);
            //开始执行动画
            bouncer.start();
            return true;
        }
    
        private void drawBall() {
            Canvas canvas = null;
            try {
                canvas = holder.lockCanvas();
                if (canvas != null) {
                    canvas.drawColor(Color.GRAY);
                    canvas.save();
                    //如果小球为空则不执行绘制动作
                    if (shapHolder != null) {
                        canvas.translate(shapHolder.getX(), shapHolder.getY());
                        shapHolder.getShape().draw(canvas);
                    }
                    canvas.restore();
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    //解锁画布
                    if (holder != null) {
                        holder.unlockCanvasAndPost(canvas);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    
        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width,
                int height) {
    
        }
    
        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            //开启绘制线程
            new Thread(this).start();
        }
    
        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
    
        }
    
        @Override
        public void run() {
            try {
                //此处为死循环,大家在写的时候可以加上一个boolean变量值,当用户点击回退键(back)时,结束线程
                while (true) {
                    drawBall();
                    Thread.sleep(200);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
    }

    二、BackgroundViewActivity.java

    package cn.yw.lib.animation;
    
    import android.app.Activity;
    import android.os.Bundle;
    
    public class BackgroundViewActivity extends Activity{
        private BackgroundView view;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            view = new BackgroundView(this);
            setContentView(view);
        }
    
    }

      

       

  • 相关阅读:
    解决Qt creator无法输入中文
    JSP 问题总结
    oracle锁与死锁概念,阻塞产生的原因以及解决方案
    QT学习记录
    使用函数式接口
    使用函数式接口来传递行为
    Prototype(原型)
    Singleton(单例)
    Factory
    Template
  • 原文地址:https://www.cnblogs.com/tony-yang-flutter/p/3580856.html
Copyright © 2011-2022 走看看