Android动画机制-属性动画(二)


在上一节Android动画机制-属性动画(一)我们简单的运用了系统给的api来完成动画,这个玩点大的。

万能动画

ofXXX的底层其实用到反射调用View中的setXXX,比如把translation写成translate那么就会报错:
sp161109_193855

因此万能的数值发生器有两种思路:
一种是使用ObjectAnimator,提供属性的setXXX和getXXX,另外一种是使用ValueAnimator

仿照小米清理垃圾的动画

Android动画机制-属性动画2038

在这里就用两种方式实现

使用ObjectAnimator

由于想要画出一个圆形,但是坐标太难计算,所以使用旋转canvas的思路

public class DrawCircle extends View {
//  设置canvas的旋转角度
    private float degress;

    public DrawCircle(Context context) {
        super(context); 
    }

    public DrawCircle(Context context, AttributeSet attrs) {
        super(context, attrs); 
    }

    public DrawCircle(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);  
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        Paint paint = new Paint();
        paint.setStrokeWidth(8);

        float width = canvas.getWidth();
        float height = canvas.getHeight();
        float radius = width / 4;

        canvas.translate(width / 2, height / 2);
//      写出正在清理垃圾请稍等
        paint.setAntiAlias(true);
        paint.setColor(Color.BLACK);
        paint.setTextSize(25);
        paint.setTextAlign(Paint.Align.CENTER);
        canvas.drawText("正在清理垃圾请稍等", 0, 0, paint);
//      画出圆形
        paint.setColor(Color.RED);
        for (float i = 0; i < degress; i += 0.01) {
            canvas.rotate(i);
            canvas.drawPoint(0, -radius, paint);
        }
    }
//   两个包装方法
    public float getDegress() {
        return degress;
    }

    public void setDegress(float degress) {
        this.degress = degress;
    }

Activity中的实现代码:

        ObjectAnimator animator = new ObjectAnimator().ofFloat(mDrawCircle, "degress", 0, 360);
        animator.setDuration(120000);
        //设置一个线性差速器
        animator.setInterpolator(new LinearInterpolator());
        //添加一个监听器
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                //通知View重绘也就是调用onDraw方法
                mDrawCircle.postInvalidate();
            }
        });
        animator.start();

使用ValueAnimator

自定义view完全一样,Activity中的实现:

        ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 360);
        //设置作用的目标
        valueAnimator.setTarget(mDrawCircle);
        valueAnimator.setInterpolator(new LinearInterpolator());
        valueAnimator.setDuration(120000);
        valueAnimator.addUpdateListener(new             ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                //得到角度
                float degress = (float) animation.getAnimatedValue();
                mDrawCircle.setDegress(degress);
                //通知重绘
                mDrawCircle.postInvalidate();
            }
        });
        valueAnimator.start();

核心思想都是一样的只不过就是使用ValueAnimator是通过在监听器中的到的角度

把自定义View和动画结合

public class DrawCircle extends View {
//  设置canvas的旋转角度
    private float degress;
//   设置自带的动画
    private ValueAnimator mAnimator;

    public DrawCircle(Context context) {
        super(context);
        initAnimator();
    }

    public DrawCircle(Context context, AttributeSet attrs) {
        super(context, attrs);
        initAnimator();
    }

    public DrawCircle(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initAnimator();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        Paint paint = new Paint();
        paint.setStrokeWidth(8);

        float width = canvas.getWidth();
        float height = canvas.getHeight();
        float radius = width / 4;

        canvas.translate(width / 2, height / 2);
//      写出正在清理垃圾请稍等
        paint.setAntiAlias(true);
        paint.setColor(Color.BLACK);
        paint.setTextSize(25);
        paint.setTextAlign(Paint.Align.CENTER);
        canvas.drawText("正在清理垃圾请稍等", 0, 0, paint);
//      画出原型
        paint.setColor(Color.RED);
        for (float i = 0; i < degress; i += 0.01) {
            canvas.rotate(i);
            canvas.drawPoint(0, -radius, paint);
        }
    }
//   两个包装方法
    public float getDegress() {
        return degress;
    }

    public void setDegress(float degress) {
        this.degress = degress;
    }

    public void startAnimator(){
//      防止重复播放动画
        mAnimator.cancel();
        mAnimator.start();
    }

    /**
     * 初始化动画
     */
    private void initAnimator() {
        ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 360);
        valueAnimator.setTarget(this);
        valueAnimator.setInterpolator(new LinearInterpolator());
        valueAnimator.setDuration(120000);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float degress = (float) animation.getAnimatedValue();
                setDegress(degress);
                invalidate();
            }
        });
        mAnimator = valueAnimator;
    }

这样只要在Avtivity中调用startAnimator即可


属性动画的核心就是一个数值发生器

在规定时间内的数值变化就形成了动画


We're here to put a dent in the universe. Otherwise why else even be here?