撸一个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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值