Android 自定义进度条控件

本文介绍Android平台下自定义进度条控件的实现方法,涵盖自定义View的XML属性定义、drawable资源文件配置(如progress_drawable)、样式主题适配,以及在Activity中通过Java/Kotlin代码动态调用与状态更新的关键步骤。

1.自定义进度条控件类

点击查看代码
package com.run.treadmill
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.RectF
import android.util.AttributeSet
import android.view.View
class CircleprogressView :View {
    constructor(context: Context) : super(context){
        init(null)
    }
    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs){
        init(attrs)
    }
    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr){
        init(attrs)
    }
    private var paintBackground = Paint()
    private var paintRedProgress = Paint()
    var progress=10f//进度 0-100
    private fun init(attrs: AttributeSet?){
        //1.自定义属性
        val typeArray = context.obtainStyledAttributes(attrs, R.styleable.CircleprogressView)
        //背景画笔和红色进度条画笔
        paintBackground= Paint().apply {
            isAntiAlias=true
            style= Paint.Style.STROKE
            color=typeArray.getColor(R.styleable.CircleprogressView_progressColor,Color.BLUE)
            strokeWidth=typeArray.getDimension(R.styleable.CircleprogressView_strokeWidth,5f)
        }
        paintRedProgress= Paint().apply {
            isAntiAlias=true
            style= Paint.Style.STROKE
            color=Color.RED
            strokeWidth=typeArray.getDimension(R.styleable.CircleprogressView_strokeWidth,8f)
        }
        typeArray.recycle()//回收
    }
    //2.测量控件大小
    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        //取宽高最小值,保证圆形不变形
        val size=minOf(widthMeasureSpec,heightMeasureSpec)
        setMeasuredDimension(size,size)
    }
    //3.绘制控件
    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)
        val center=measuredWidth/2f
        val radius=center-paintBackground.strokeWidth
        //背景圆形
        canvas?.drawCircle(center,center,radius,paintBackground)//cx cy
        //进度圆弧
        val sweepAngle=progress/100*360//center-(center-paint.strokeWidth)
         //绘制弧形或扇形的正方形边框
        var rectFProgress=RectF(center-radius,center-radius,center+radius,center+radius)//左 上  右  下
//        canvas?.drawRect(rectFProgress,paintRedProgress)
        canvas?.drawArc(rectFProgress,
            -90f,sweepAngle,false,paintRedProgress)//startAngle sweepAngle  是否连接圆心
    }
    //更新进度条
    fun updateProgress(value: Float){
        progress=value.coerceIn(0f,100f)
        invalidate()
    }
}

**2.xml引入文件 **

点击查看代码
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/cl_home"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/color_3a6a63">
    <com.run.treadmill.CircleprogressView
        android:id="@+id/cv"
        app:progressColor="@color/white"
        app:strokeWidth="5dp"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
    </androidx.constraintlayout.widget.ConstraintLayout>

3.attrs文件

点击查看代码
<declare-styleable name="CircleprogressView">
    <attr name="progressColor" format="color" />
    <attr name="strokeWidth" format="dimension" />
</declare-styleable>

4.activity调用

点击查看代码
//自动更新进度
lifecycleScope.launch{
    var p=0f
    while (p<=100f){
        cv.updateProgress(p)
        p++
        delay(1000)
    }
}
posted @ 2026-10-21 10:59  xiao250  阅读(2)  评论(0)    收藏  举报