【5年Android从零复盘系列之十三】Android自定义View(8):绘制动画详解(图文)

1.简述

自定义view绘制动画原理就是,定义一个value值,值随着动画进度改变而改变;在onDraw()中,绘制时使其中某个或多个参数值*value/100(假设设置动画进度最大值100);而后设置动画对象时,value每次变化时,调用postInvalidate()通知视图重绘,从而再次调用onDraw()…如此循环,从而实现绘制动画。

2.使用

实际使用效果:

2.1代码解释

2.1.1 动画控制

    private int animProgress = 0;//定义一个 跟随动画进度变化的value值
    private ValueAnimator mAnimtor  ;
    public void startAnim(){
        if (mAnimtor == null){
            mAnimtor = ValueAnimator.ofInt(0,100);
            mAnimtor.setDuration(800);//动画持续时长
            mAnimtor.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator valueAnimator) {
                    animProgress = (int) valueAnimator.getAnimatedValue();
                    postInvalidate();
                }
            });
        }
        mAnimtor.start();
    }

2.1.2初始化绘制

    private Paint mPaint;
    private Path mPath;

    public DiyViewAnim(Context context) {
        super(context);
        mPaint = new Paint();
        mPath = new Path();
    }

    public DiyViewAnim(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        mPaint = new Paint();
        mPath = new Path();
    }

2.1.3根据value值动态绘制

其中条形图绘制数值意义可参考自定义view(4):自绘式

 @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mPaint.reset();
        mPath.reset();
        //1.画坐标轴
        mPaint.setColor(Color.parseColor("#404040"));
        mPaint.setStyle(Paint.Style.STROKE);
        mPath.moveTo(120, 120);//y轴顶点(120,120)
        mPath.rLineTo(0, 600);//y轴方向
        mPath.rLineTo(800, 0);//x轴方向
        canvas.drawPath(mPath, mPaint);//绘制
        //2.画x轴label
        mPaint.reset();
        mPaint.setColor(Color.parseColor("#404040"));
        mPaint.setTextSize(18);//px
        mPaint.setStyle(Paint.Style.FILL);
        //假数据
        canvas.drawText("1月", 120 + 20, 120 + 600 + 28, mPaint);
        canvas.drawText("2月", 120 + 20 * 2 + 60 * (2 - 1), 600 + 120 + 28, mPaint);
        canvas.drawText("3月", 120 + 20 * 3 + 60 * (3 - 1), 600 + 120 + 28, mPaint);
        //3.画条形图
        float[] lines = {
                120 + 20 * (1) + 60 * ((1) - 1 + 0.5f),
                  600 + 120,
                120 + 20 * (1) + 60 * ((1) - 1 + 0.5f),
                600 + 120 - 180*animProgress/100,
                120 + 20 * (2) + 60 * ((2) - 1 + 0.5f),
                600 + 120,
                120 + 20 * (2) + 60 * ((2) - 1 + 0.5f),
                600 + 120 - 420*animProgress/100,
                120 + 20 * (3) + 60 * ((3) - 1 + 0.5f),
                600 + 120,
                120 + 20 * (3) + 60 * ((3) - 1 + 0.5f),
                600 + 120 - 140*animProgress/100
        };
        mPaint.reset();
        mPaint.setColor(Color.parseColor("#6ce4d8"));
        mPaint.setStrokeWidth(60);
        canvas.drawLines(lines, mPaint);
    }

2.2 xml使用

        <com.cupster.base_super_resource.DiyViewAnim
            android:id="@+id/diy_chart"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            />
         DiyViewAnim diyChart = findViewById(R.id.diy_chart);
         diyChart.startAnim();

3.完整View代码

package com.cupster.base_super_resource;

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

import androidx.annotation.Nullable;

public class DiyViewAnim extends View {
    public DiyViewAnim(Context context) {
        super(context);
        mPaint = new Paint();
        mPath = new Path();
    }

    public DiyViewAnim(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        mPaint = new Paint();
        mPath = new Path();
    }

    public DiyViewAnim(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mPaint = new Paint();
        mPath = new Path();
    }

    public DiyViewAnim(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        mPaint = new Paint();
        mPath = new Path();
    }

    private Paint mPaint;
    private Path mPath;

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mPaint.reset();
        mPath.reset();
        //1.画坐标轴
        mPaint.setColor(Color.parseColor("#404040"));
        mPaint.setStyle(Paint.Style.STROKE);
        mPath.moveTo(120, 120);//y轴顶点(120,120)
        mPath.rLineTo(0, 600);//y轴方向
        mPath.rLineTo(800, 0);//x轴方向
        canvas.drawPath(mPath, mPaint);//绘制
        //2.画x轴label
        mPaint.reset();
        mPaint.setColor(Color.parseColor("#404040"));
        mPaint.setTextSize(18);//px
        mPaint.setStyle(Paint.Style.FILL);
        //假数据
        canvas.drawText("1月", 120 + 20, 120 + 600 + 28, mPaint);
        canvas.drawText("2月", 120 + 20 * 2 + 60 * (2 - 1), 600 + 120 + 28, mPaint);
        canvas.drawText("3月", 120 + 20 * 3 + 60 * (3 - 1), 600 + 120 + 28, mPaint);
        //3.画条形图
        float[] lines = {
                120 + 20 * (1) + 60 * ((1) - 1 + 0.5f),
                  600 + 120,
                120 + 20 * (1) + 60 * ((1) - 1 + 0.5f),
                600 + 120 - 180*animProgress/100,
                120 + 20 * (2) + 60 * ((2) - 1 + 0.5f),
                600 + 120,
                120 + 20 * (2) + 60 * ((2) - 1 + 0.5f),
                600 + 120 - 420*animProgress/100,
                120 + 20 * (3) + 60 * ((3) - 1 + 0.5f),
                600 + 120,
                120 + 20 * (3) + 60 * ((3) - 1 + 0.5f),
                600 + 120 - 140*animProgress/100
        };
        mPaint.reset();
        mPaint.setColor(Color.parseColor("#6ce4d8"));
        mPaint.setStrokeWidth(60);
        canvas.drawLines(lines, mPaint);
    }
    
    private int animProgress = 0;
    private ValueAnimator mAnimtor  ;
    public void startAnim(){
        if (mAnimtor == null){
            mAnimtor = ValueAnimator.ofInt(0,100);
            mAnimtor.setDuration(800);
            mAnimtor.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator valueAnimator) {
                    animProgress = (int) valueAnimator.getAnimatedValue();
                    postInvalidate();
                }
            });
        }
        mAnimtor.start();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值