撸一个Android环形进度条

环形进度条在开发中用的也不算少。今天来手动撸一个。

首先,定义一个 CircleProgressView,继承自View:

import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.LinearInterpolator;

import com.yikelive.R;

import androidx.annotation.Nullable;

/**
 * 普通环形进度条
 */
public class CircleProgressView extends View {
    
    
    /**
     * 当前进度
     */
    private int mCurrent;
    /**
     * 背景弧线paint
     */
    private Paint mBgPaint;
    /**
     * 进度Paint
     */
    private Paint mProgressPaint;
    /**
     * 进度条宽度
     */
    private float mProgressWidth;
    /**
     * 进度条颜色
     */
    private int mProgressColor = Color.RED;
    /**
     * 开始角度
     */
    private float startAngle;
    private final RectF rectF = new RectF();
    private ValueAnimator mAnimator;
    private int max = 0;

    public CircleProgressView(Context context) {
    
    
        this(context, null);
    }

    public CircleProgressView(Context context, @Nullable AttributeSet attrs) {
    
    
        this(context, attrs, 0);
    }

    public CircleProgressView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    
    
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {
    
    
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CircleProgressView);
        //起始位置
        startAngle = typedArray.getInt(R.styleable.CircleProgressView_location_start, 1);
        mProgressWidth = typedArray.getDimension(R.styleable.CircleProgressView_progress_width, dp2px(context, 4));
        mProgressColor = typedArray.getColor(R.styleable.CircleProgressView_progress_color, mProgressColor);
        typedArray.recycle();

        //背景圆弧
        mBgPaint = new Paint();
        mBgPaint.setAntiAlias(true);
        mBgPaint.setStrokeWidth(mProgressWidth);
        mBgPaint.setStyle(Paint.Style.STROKE);
        mBgPaint.setColor(Color.parseColor("#888888"));
        mBgPaint.setStrokeCap(Paint.Cap.ROUND);

        //进度圆弧
        mProgressPaint = new Paint();
        mProgressPaint.setAntiAlias(true);
        mProgressPaint.setStyle(Paint.Style.STROKE);
        mProgressPaint.setStrokeWidth(mProgressWidth);
        mProgressPaint.setColor(mProgressColor);
        mProgressPaint.setStrokeCap(Paint.Cap.ROUND);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    
    
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        int size = Math.min(width, height);
        setMeasuredDimension(
                MeasureSpec.makeMeasureSpec(size, MeasureSpec.getMode(widthMeasureSpec)),
                MeasureSpec.makeMeasureSpec(size, MeasureSpec.getMode(heightMeasureSpec))
        );
        // 圆弧尺寸
        rectF.set(mProgressWidth / 2,
                mProgressWidth / 2,
                width - mProgressWidth / 2,
                height - mProgressWidth / 2);
    }

    /**
     * oval  // 绘制范围
     * startAngle  // 开始角度
     * sweepAngle  // 扫过角度
     * useCenter   // 是否使用中心
     */
    @Override
    protected void onDraw(Canvas canvas) {
    
    
        //绘制背景圆弧
        canvas.drawArc(rectF, 0, 360, false, mBgPaint);

        //绘制当前进度
        float sweepAngle = 360 * mCurrent / max;
        canvas.drawArc(rectF, startAngle, sweepAngle, false, mProgressPaint);
    }

    @Override
    protected void onDetachedFromWindow() {
    
    
        super.onDetachedFromWindow();
        destroy();
    }

    public void setMax(int max) {
    
    
        this.max = max;
    }

    public int getCurrent() {
    
    
        return mCurrent;
    }

    /**
     * 设置进度
     *
     * @param current
     */
    public void setCurrent(int current) {
    
    
        mCurrent = current;
        invalidate();
    }

    private int tCurrent = -1;

    /**
     * 动画效果
     *
     * @param current  精度条进度:0-100
     * @param duration 动画时间
     */
    public void startAnimProgress(int current, int duration) {
    
    
        mAnimator = ValueAnimator.ofInt(0, current);
        mAnimator.setDuration(duration);
        mAnimator.setInterpolator(new LinearInterpolator());
        mAnimator.addUpdateListener(animation -> {
    
    
            int current1 = (int) animation.getAnimatedValue();
            if (tCurrent != current1) {
    
    
                tCurrent = current1;
                setCurrent(current1);
                if (mOnAnimProgressListener != null) {
    
    
                    mOnAnimProgressListener.valueUpdate(current1);
                }
            }
        });
        mAnimator.start();
    }

    public interface OnAnimProgressListener {
    
    
        void valueUpdate(int progress);
    }

    private OnAnimProgressListener mOnAnimProgressListener;

    /**
     * 监听进度条进度
     *
     * @param onAnimProgressListener
     */
    public void setOnAnimProgressListener(OnAnimProgressListener onAnimProgressListener) {
    
    
        mOnAnimProgressListener = onAnimProgressListener;
    }

    public void destroy() {
    
    
        if (mAnimator != null) {
    
    
            mAnimator.cancel();
        }
    }

    public static int dp2px(Context context, float dpValue) {
    
    
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }
}

进度条的View就算完了。说下使用方法

属性 释义
progress_color 进度条进度颜色
progress_width 进度条宽度
progress.setMax(int size) 设置总进度值
progress.setCurrent(int current) 设置当前进度值

至于进度条的默认颜色(弧线默认颜色),可直接在代码中设置:

mBgPaint.setColor(Color.parseColor("#888888"));

在这里插入图片描述

到此。进度条就算完成了。
END

猜你喜欢

转载自blog.csdn.net/lixinxiaos/article/details/105534394