自定义圆环形进度条实现(代码片段)

我叫白小飞 我叫白小飞     2022-12-15     539

关键词:

最近项目里边要用进度条,进度条中间展示进度,底部展示label,因为这个组件用的地方多,所以我就直接封装了一个通用组件。

先看一下效果图:

功能有:
  1. 圆环的颜色和进度可以自定义;
  2. 中间文字可以自定义;
  3. 可以自定义圆环的宽度;
  4. 可以设置底部文字(文字内容、大小和textStyle);
  5. 提供设置进度的接口;
  6. 可以设置进度的最大值;
下边开始编码:
  1. 首先继承定义一个类继承自View,因为我们需要提供一些可配置的自定义属性:
public class CircleProgress extends View 

	private final Paint mPaint; // 画笔
    private final RectF mRectF;
    private final Rect mRect;
    private final Paint mBottomPaint; // 绘制底部文字
    private int mCurrent; // 当前进度
    private int mMax; // 最大进度
    private int mWidth; // 当前view设置的宽度

	public CircleProgress(Context context) 
        this(context,null);
    

    public CircleProgress(Context context, @Nullable AttributeSet attrs) 
        this(context, attrs,0);
    

    public CircleProgress(Context context, @Nullable AttributeSet attrs, int defStyleAttr) 
        super(context, attrs, defStyleAttr);
        initAttr(context,attrs);
        mPaint = new Paint();
        mBottomPaint = new Paint();
        mBottomPaint.setAntiAlias(true);
        mPaint.setAntiAlias(true);
        mRectF = new RectF();
        mRect = new Rect();
    



  1. 自定义属性,在attr.xml中新建一个declare-styleable,并命名为:CircleProgress
<!-- 圆环进度条 -->
    <declare-styleable name="CircleProgress">
        <attr name="max_progress" format="integer"/>
        <attr name="arc_bg_color" format="color"/>
        <attr name="arc_color" format="color"/>
        <attr name="arc_width" format="dimension"/>
        <attr name="mid_text_size" format="dimension"/>
        <attr name="bottom_text_size" format="dimension"/>
        <attr name="bottom_text" format="string" localization="suggested"/>
        <attr name="textStyle">
            <flag name="normal" value="0" />
            <flag name="bold" value="1" />
        </attr>
    </declare-styleable>
  1. 然后我们在initAttr()方法中解析这些属性,解析出来的属性,后边在绘制的时候需要用到:
  private void initAttr(Context context, AttributeSet attrs) 
        TypedArray attributes = context.obtainStyledAttributes(attrs,R.styleable.CircleProgress);
        mMax = attributes.getInteger(R.styleable.CircleProgress_max_progress, 100);
        mCircleBGColor = attributes.getColor(R.styleable.CircleProgress_arc_bg_color,context.getResources().getColor(R.color.color_d1, null));
        mCircleColor = attributes.getColor(R.styleable.CircleProgress_arc_color,context.getResources().getColor(R.color.colorRed, null));
        mArcWidth = attributes.getDimensionPixelOffset(R.styleable.CircleProgress_arc_width,SizeUtils.dp2px(20));
        mPercentTextSize = attributes.getDimensionPixelOffset(R.styleable.CircleProgress_mid_text_size,SizeUtils.sp2px(12));
        mBottomTextSize = attributes.getDimensionPixelOffset(R.styleable.CircleProgress_bottom_text_size,SizeUtils.sp2px(14));
        mBottomTextId = attributes.getResourceId(R.styleable.CircleProgress_bottom_text,0);
        mBottomText = attributes.getText(R.styleable.CircleProgress_bottom_text).toString();
        mBottomTextType = attributes.getInt(R.styleable.CircleProgress_textStyle,0);
        attributes.recycle();
    
  1. 解析完属性之后,就可以开始绘制了,绘制主要按照顺序绘制,我们先绘制圆环,在绘制百分比,然后绘制底部文字:
@Override
    protected void onDraw(Canvas canvas) 
        super.onDraw(canvas);
        //绘制圆形
        //设置为空心圆,如果不理解绘制弧线是什么意思就把这里的属性改为“填充”,跑一下瞬间就明白了
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setAntiAlias(true);
        //设置圆弧的宽度(圆环的宽度)
        mPaint.setStrokeWidth(mArcWidth);
        mPaint.setColor(mCircleBGColor);
        //大圆的半径
        float bigCircleRadius = mWidth / 2;
        // 小圆的半径
        float smallCircleRadius = bigCircleRadius - mArcWidth;
        // 绘制小圆
        canvas.drawCircle(bigCircleRadius,bigCircleRadius,smallCircleRadius,mPaint);
        mPaint.setColor(mCircleColor);
        mRectF.set(mArcWidth,mArcWidth,mWidth - mArcWidth,mWidth - mArcWidth);
        // 绘制圆弧
        canvas.drawArc(mRectF,90f,mCurrent * 360f / mMax, false, mPaint);
        // 计算百分比
        String percent = mCurrent * 100 / mMax + "%";
        mPaint.setStrokeWidth(0);
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setTextSize(mPercentTextSize);
        mPaint.getTextBounds(percent, 0, percent.length(), mRect);
        mPaint.setColor(mCircleColor);
        // 绘制百分比
        canvas.drawText(percent,bigCircleRadius- mRect.width() / 2, bigCircleRadius + mRect.height() / 2, mPaint);
        // 绘制底部文字
        if (!TextUtils.isEmpty(mBottomText)) 
            mBottomPaint.setStrokeWidth(0);
            mBottomPaint.setTextSize(mBottomTextSize);
            mBottomPaint.getTextBounds(mBottomText.toString(),0, mBottomText.toString().length(),mRect);
            mBottomPaint.setColor(Color.BLACK);
            if (mBottomTextType == 1) 
                Typeface tf = Typeface.DEFAULT_BOLD;
                mBottomPaint.setTypeface(tf);
            
            canvas.drawText(mBottomText.toString(),bigCircleRadius - mRect.width() / 2f, mWidth + mRect.height(), mBottomPaint);
         else if(mBottomTextId > 0)
            String bottomText = getResources().getString(mBottomTextId);
            mBottomPaint.setStrokeWidth(0);
            mBottomPaint.setTextSize(mBottomTextSize);
            mBottomPaint.getTextBounds(bottomText,0, bottomText.length(),mRect);
            mBottomPaint.setColor(Color.BLACK);
            if (mBottomTextType == 1) 
                Typeface tf = Typeface.DEFAULT_BOLD;
                mBottomPaint.setTypeface(tf);
            
            canvas.drawText(bottomText,bigCircleRadius - mRect.width() / 2f, mWidth + mRect.height(), mBottomPaint);
        
    
  1. 编译之后就可以在布局文件中使用了:
 <com.towngas.top.commonlibrary.widget.CircleProgress
                    android:id="@+id/cp_timeliness_patrol"
                    android:layout_width="0dp"
                    android:layout_weight="1"
                    android:layout_height="match_parent"
                    app:max_progress="100"
                    app:arc_width="@dimen/dp_12"
                    app:arc_bg_color="#FBCCA0"
                    app:arc_color="#FBCCA0"
                    app:bottom_text_size="@dimen/sp_14"
                    app:textStyle="bold"
                    app:bottom_text="下载"/>
完整代码:
public class CircleProgress extends View 


    private final Paint mPaint; // 画笔
    private final RectF mRectF;
    private final Rect mRect;
    private final Paint mBottomPaint; // 绘制底部文字
    private int mCurrent; // 当前进度
    private int mMax; // 最大进度
    private int mWidth; // 当前view设置的宽度

    //圆弧(也可以说是圆环)的宽度
    private float mArcWidth;
    private int mCircleBGColor; // 自定义圆环背景color
    private int mCircleColor; // 自定义圆环clolr
    private int mBottomTextId = Resources.ID_NULL; // 底部文字
    private CharSequence mBottomText; //底部文字
    private float mPercentTextSize; // 百分比文字大小
    private float mBottomTextSize; // 底部文字大小
    private int mBottomTextType; // 字体样式

    public CircleProgress(Context context) 
        this(context,null);
    

    public CircleProgress(Context context, @Nullable AttributeSet attrs) 
        this(context, attrs,0);
    

    public CircleProgress(Context context, @Nullable AttributeSet attrs, int defStyleAttr) 
        super(context, attrs, defStyleAttr);
        initAttr(context,attrs);
        mPaint = new Paint();
        mBottomPaint = new Paint();
        mBottomPaint.setAntiAlias(true);
        mPaint.setAntiAlias(true);
        mRectF = new RectF();
        mRect = new Rect();
    

    private void initAttr(Context context, AttributeSet attrs) 
        TypedArray attributes = context.obtainStyledAttributes(attrs,R.styleable.CircleProgress);
        mMax = attributes.getInteger(R.styleable.CircleProgress_max_progress, 100);
        mCircleBGColor = attributes.getColor(R.styleable.CircleProgress_arc_bg_color,context.getResources().getColor(R.color.color_d1, null));
        mCircleColor = attributes.getColor(R.styleable.CircleProgress_arc_color,context.getResources().getColor(R.color.colorRed, null));
        mArcWidth = attributes.getDimensionPixelOffset(R.styleable.CircleProgress_arc_width,SizeUtils.dp2px(20));
        mPercentTextSize = attributes.getDimensionPixelOffset(R.styleable.CircleProgress_mid_text_size,SizeUtils.sp2px(12));
        mBottomTextSize = attributes.getDimensionPixelOffset(R.styleable.CircleProgress_bottom_text_size,SizeUtils.sp2px(14));
        mBottomTextId = attributes.getResourceId(R.styleable.CircleProgress_bottom_text,0);
        mBottomText = attributes.getText(R.styleable.CircleProgress_bottom_text).toString();
        mBottomTextType = attributes.getInt(R.styleable.CircleProgress_textStyle,0);
        attributes.recycle();
    


    /**
     * 设置当前进度
     * @param current
     */
    public void SetCurrent(int current) 
        this.mCurrent = current;
        invalidate();
    

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) 
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //getMeasuredWidth获取的是view的原始大小,也就是xml中配置或者代码中设置的大小
        //getWidth获取的是view最终显示的大小,这个大小不一定等于原始大小
        mWidth = getMeasuredWidth();
    

    @Override
    protected void onDraw(Canvas canvas) 
        super.onDraw(canvas);
        //绘制圆形
        //设置为空心圆,如果不理解绘制弧线是什么意思就把这里的属性改为“填充”,跑一下瞬间就明白了
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setAntiAlias(true);
        //设置圆弧的宽度(圆环的宽度)
        mPaint.setStrokeWidth(mArcWidth);
        mPaint.setColor(mCircleBGColor);
        //大圆的半径
        float bigCircleRadius = mWidth / 2;
        // 小圆的半径
        float smallCircleRadius = bigCircleRadius - mArcWidth;
        // 绘制小圆
        canvas.drawCircle(bigCircleRadius,bigCircleRadius,smallCircleRadius,mPaint);
        mPaint.setColor(mCircleColor);
        mRectF.set(mArcWidth,mArcWidth,mWidth - mArcWidth,mWidth - mArcWidth);
        // 绘制圆弧
        canvas.drawArc(mRectF,90f,mCurrent * 360f / mMax, false, mPaint);
        // 计算百分比
        String percent = mCurrent * 100 / mMax + "%";
        mPaint.setStrokeWidth(0);
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setTextSize(mPercentTextSize);
        mPaint.getTextBounds(percent, 0, percent.length(), mRect);
        mPaint.setColor(mCircleColor);
        // 绘制百分比
        canv

qt编写自定义控件14-环形进度条(代码片段)

前言环形进度条,用来展示当前进度,为了满足大屏UI的需要特意定制,以前有个叫圆环进度条,不能满足项目需要,只能重新定做,以前的进度间距不能自适应分辨率,而且当前进度对应的反的进度不能单独设置颜色,即当前... 查看详情

酷炫进度条自定义seekbar(代码片段)

前些天一同学给了我一个ui图,是这样子的:需求:1、看了ui图可以知道这类似android自带的seekbar控件,2、一个水平进度条和一个圆形进度条;3、圆形进度条显示环形刻度和当前进度值;4、并且圆形进度... 查看详情

一起talkandroid吧(第四百九十六回:自定义view实例二:环形进度条)

...是"如何使用Java版MQTT客户端",这一回中咱们说的例子是"自定义View实例二:环形进度条"。闲话休提,言归正转,让我们一起TalkAndroid吧!知识回顾看官们,我们又回到了自定义View相关的知识中,在这里对旧知识做一些回顾:首先... 查看详情

echarts实现环形进度条(代码片段)

效果图实现代码可直接复制运行:<!DOCTYPEhtml><html> <head> <metacharset="UTF-8"> <title>环形进度条</title> <scriptsrc="https://cdn.staticfile.org/echart 查看详情

compose自定义条形进度条(代码片段)

前言Compose自定义View其实比View系统更方便简单,比如接下来本文要介绍的就是使用Compose实现View系统中常见的条形进度条。自定义进度条Composematerial包中提供了CircularProgressIndicator实现View系统中的圆形进度条,因为Compose没... 查看详情

compose自定义条形进度条(代码片段)

前言Compose自定义View其实比View系统更方便简单,比如接下来本文要介绍的就是使用Compose实现View系统中常见的条形进度条。自定义进度条Composematerial包中提供了CircularProgressIndicator实现View系统中的圆形进度条,因为Compose没... 查看详情

用svg实现一个环形进度条(代码片段)

svg实现环形进度条需要用到的知识:1、会使用path的d属性画一个圆环2、熟悉stroke,stroke-linecap,stroke-width,stroke-dasharray、stroke-dashoffset 话不多说,直接上代码<divstyle="width:200px;height:200px;"><svgviewBox="00100100">&l 查看详情

图解css3制作圆环形进度条的实例教程

圆环形进度条制作的基本思想还是画出基本的弧线图形,然后CSS3中我们可以控制其旋转来串联基本图形,制造出部分消失的效果,下面就来带大家学习图解CSS3制作圆环形进度条的实例教程首先,当有人说你能不能做一个圆形进度条... 查看详情

compose自定义条形进度条(代码片段)

前言Compose自定义View其实比View系统更方便简单,比如接下来本文要介绍的就是使用Compose实现View系统中常见的条形进度条。自定义进度条Composematerial包中提供了CircularProgressIndicator实现View系统中的圆形进度条,因为Compose没... 查看详情

用初中数学知识撸一个canvas环形进度条(代码片段)

周末好,今天给大家带来一款接地气的环形进度条组件vue-awesome-progress。近日被设计小姐姐要求实现这么一个环形进度条效果,大体由四部分组成,分别是底色圆环,进度弧,环内文字,进度圆点。设计稿截图如下:我的第一反... 查看详情

android自定义圆弧进度条(代码片段)

...到合适,干脆就自己写了一个,顺便复习一下自定义View,下面是具体的实现。先看一下效果这里的话我只做一个进度条 查看详情

csssvg环形进度条-5(代码片段)

查看详情

htmlsvg环形进度条-7(代码片段)

查看详情

csssvg环形进度条-3。(代码片段)

查看详情

htmlsvg环形进度条-4(代码片段)

查看详情

htmlsvg环形进度条-2(代码片段)

查看详情

htmlsvg环形进度条-1(代码片段)

查看详情

仿字节颜色自定义android进度条(代码片段)

效果展示代码实现第一步:编写自定义属性 res/values/attrs.xml<?xmlversion="1.0"encoding="utf-8"?><resources><declare-styleablename="MyLoadingView"><attrname="loading_color_one"format="color"/> 查看详情