Android 圆形进度条CircleProgressView 基础版

一个最基础的自定义View 圆形进度条,可设置背景色、进度条颜色(渐变色)下载进度控制;可二次定制度高;

核心代码:

复制代码
    @Override
    protected void onDraw(@NonNull Canvas canvas) {
        super.onDraw(canvas);
        int mW = getMeasuredWidth();
        int mH = getMeasuredHeight();
        int centerX = mW/2;
        int centerY = mH/2;
        Log.i(TAG, "onDraw: "+mW +"-" +mH);

        //画背景色
        canvas.save();
        paintBg.setColor(backgroundColor);
        RectF rectBg = new RectF(strokeWidth,strokeWidth,mW-strokeWidth,mH-strokeWidth);
        canvas.drawArc(rectBg,0,360,false , paintBg);

        //画进度条颜色
        float ratio  = (float) Math.min(progress / max , 1.00);
        paint.setColor(loadingColor); //设置进度条颜色
//        SweepGradient sweepGradient = new SweepGradient(centerX , centerY , new int[]{loadingColor , Color.YELLOW} , null);
//        paint.setShader(sweepGradient); //设置进度条渐变色
        paint.setStrokeCap(Paint.Cap.ROUND); 设置画笔边缘为半圆状
        canvas.drawArc(rectBg,0,360*ratio,false , paint);
        canvas.restore();

        //画中间的文案
        paintText.setTextSize(dp2px(18));
        paintText.setColor(Color.BLACK);
        paintText.setTextAlign(Paint.Align.CENTER);
        Paint.FontMetrics fontMetrics = paintText.getFontMetrics();
        float disY = (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom;
        canvas.drawText(progress+"%" , centerX , centerY+disY , paintText);

    }

全部代码:

复制代码
package com.cuichen.mytestdemo.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.SweepGradient;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.cuichen.mytestdemo.R;

public class CircleProgressView extends View {
    private final String TAG = CircleProgressView.class.getSimpleName();
    public CircleProgressView(Context context) {
        super(context);
    }

    public CircleProgressView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        initAttrs(attrs);
    }

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

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

    private void initAttrs( @Nullable AttributeSet attrs){
        TypedArray typedArray = getContext().obtainStyledAttributes(attrs , R.styleable.CircleProgress);
        try{
            backgroundColor = typedArray.getColor(R.styleable.CircleProgress_backgroundColorCircle , Color.parseColor("#5503DAC5"));
            loadingColor = typedArray.getColor(R.styleable.CircleProgress_progressColorCircle ,Color.parseColor("#FF018786"));
            strokeWidth = (int) typedArray.getDimension(R.styleable.CircleProgress_strokeWidthCircle , 18);
            max = typedArray.getInt(R.styleable.CircleProgress_maxCircle , 100);
            progress = typedArray.getInt(R.styleable.CircleProgress_progressCircle , 50);
        }catch (Exception e){
            typedArray.recycle();
        }

    }


    private int strokeWidth = 18;
    private float progress = 0f;
    private float max = 100f;
    private int backgroundColor;
    private int loadingColor;

    final int DEFAULT_HEIGHT_DP = 66;

    Paint paintBg , paint , paintText;
    void init(){
        paintBg = new Paint();
        paintBg.setAntiAlias(true);
        paintBg.setStyle(Paint.Style.STROKE);
        paintBg.setStrokeWidth(strokeWidth);

        paint = new Paint();
        paint.setAntiAlias(true);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(strokeWidth);

        paintText = new Paint();
        paintText.setAntiAlias(true);

    }

    public void setProgress(int progress){
        this.progress = progress;
        invalidate();
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        Log.i(TAG, "onMeasure: ");
        int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
        int height = 0;
        switch (heightSpecMode){
            case MeasureSpec.AT_MOST:
                height = dp2px(DEFAULT_HEIGHT_DP);
                break;
            case MeasureSpec.EXACTLY:
            case MeasureSpec.UNSPECIFIED:
                height = heightSpecSize;
                break;
        }
        setMeasuredDimension(widthSpecSize, height);

        if(paint == null) {
            init();
        }
    }

    //RectF
    //left:左边坐标;在绘制中常表示为起点的Y轴坐标
    //top:上边左边;在绘制中常表示为起点的X轴坐标
    //right:右边坐标;在绘制中常表示为终点的X轴坐标
    //bottom:下边坐标;在绘制中常表示为终点的Y轴坐标
    @Override
    protected void onDraw(@NonNull Canvas canvas) {
        super.onDraw(canvas);
        int mW = getMeasuredWidth();
        int mH = getMeasuredHeight();
        int centerX = mW/2;
        int centerY = mH/2;
        Log.i(TAG, "onDraw: "+mW +"-" +mH);

        //画背景色
        canvas.save();
        paintBg.setColor(backgroundColor);
        RectF rectBg = new RectF(strokeWidth,strokeWidth,mW-strokeWidth,mH-strokeWidth);
        canvas.drawArc(rectBg,0,360,false , paintBg);

        //画进度条颜色
        float ratio  = (float) Math.min(progress / max , 1.00);
        paint.setColor(loadingColor); //设置进度条颜色
//        SweepGradient sweepGradient = new SweepGradient(centerX , centerY , new int[]{loadingColor , Color.YELLOW} , null);
//        paint.setShader(sweepGradient); //设置进度条渐变色
        paint.setStrokeCap(Paint.Cap.ROUND); 设置画笔边缘为半圆状
        canvas.drawArc(rectBg,0,360*ratio,false , paint);
        canvas.restore();

        //画中间的文案
        paintText.setTextSize(dp2px(18));
        paintText.setColor(Color.BLACK);
        paintText.setTextAlign(Paint.Align.CENTER);
        Paint.FontMetrics fontMetrics = paintText.getFontMetrics();
        float disY = (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom;
        canvas.drawText(progress+"%" , centerX , centerY+disY , paintText);

    }
    private int dp2px(int dp){
        float density = getContext().getResources().getDisplayMetrics().density;
        return (int) (dp * density);
    }
}

    <declare-styleable name="CircleProgress">
        <attr name="backgroundColorCircle" format="color"/>
        <attr name="progressColorCircle" format="color"/>
        <attr name="strokeWidthCircle" format="dimension"/>
        <attr name="maxCircle" format="integer"/>
        <attr name="progressCircle" format="integer"/>
    </declare-styleable>
相关推荐
三少爷的鞋11 分钟前
协程深度解析:明明只有 8 个异步任务,为何 App 线程数瞬间突破 一倍?
android
GitLqr10 小时前
Flutter 3.44 插件内置 Kotlin (KGP) 双向兼容适配指南
android·flutter·dart
随遇丿而安14 小时前
第11周:Activity 跳转与传值 + 跳转优化
android
私人珍藏库15 小时前
[Android] BBLL 开源第三方B哩电视TV端
android·app·生活·工具·多功能
杉氧17 小时前
跨平台资源管理:一套代码如何搞定 Android、iOS 和 Web 的图片与多语言?
android·架构·android jetpack
安卓修改大师19 小时前
安卓修改大师实战:从反编译到定制的完整APK修改指南
android
柚鸥ASO优化20 小时前
安卓APP推广的“降本增效”密码:守好商店内,打好商店外
android·aso优化
我是一颗柠檬20 小时前
【Java项目技术亮点】EXPLAIN深度分析与慢查询治理
android·java·开发语言
Android-Flutter20 小时前
android compose shadow 阴影 使用
android·kotlin·compose
帅次21 小时前
Android 高级工程师面试:Java 多线程与并发 近1年高频追问 22 题
android·java·面试