You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Android平台的Circular Progress Bar添加圆角效果?

环形进度条圆角实现方案

原生XML定义的ring形状在Android 12(API 31)以下版本未提供进度端点圆角的配置能力,可通过以下两种方案实现需求:

方案1:API 31+ 原生XML实现

如果应用最低兼容版本为Android 12,直接修改custom_progress_drawable.xml的进度层shape,添加android:cornersRadius属性,值设置为环厚度的一半(当前厚度为10dp,设为5dp即可):

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape
            android:shape="ring"
            android:thicknessRatio="16"
            android:useLevel="false"
            android:thickness="10dp">
            <solid android:color="@color/base_dark" />
        </shape>
    </item>
    <item>
        <rotate
            android:fromDegrees="270"
            android:toDegrees="270">
            <shape
                android:shape="ring"
                android:thicknessRatio="16"
                android:useLevel="true"
                android:thickness="10dp"
                android:cornersRadius="5dp">
                <gradient
                    android:endColor="@color/secundary_10"
                    android:type="radial"/>
            </shape>
        </rotate>
    </item>
</layer-list>

方案2:全版本兼容自定义实现

如果需要兼容Android 12以下版本,通过自定义Drawable实现,核心逻辑是利用Paint的圆角笔触属性绘制圆弧:

自定义Drawable示例代码

class RoundedCircularProgressDrawable(
    private val bgColor: Int,
    private val progressColor: Int,
    private val strokeWidth: Float
) : Drawable() {

    private val bgPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
        style = Paint.Style.STROKE
        this.strokeWidth = this@RoundedCircularProgressDrawable.strokeWidth
        color = bgColor
        strokeCap = Paint.Cap.ROUND
    }

    private val progressPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
        style = Paint.Style.STROKE
        this.strokeWidth = this@RoundedCircularProgressDrawable.strokeWidth
        color = progressColor
        strokeCap = Paint.Cap.ROUND // 该属性控制进度端点为圆角
    }

    var progress: Float = 0f
        set(value) {
            field = value.coerceIn(0f, 1f)
            invalidateSelf()
        }

    override fun draw(canvas: Canvas) {
        val rect = bounds
        val radius = (rect.width() - strokeWidth) / 2f
        val centerX = rect.exactCenterX()
        val centerY = rect.exactCenterY()
        // 绘制背景环
        canvas.drawCircle(centerX, centerY, radius, bgPaint)
        // 绘制进度弧,从270度开始绘制对应进度的角度
        canvas.drawArc(
            centerX - radius,
            centerY - radius,
            centerX + radius,
            centerY + radius,
            270f,
            progress * 360f,
            false,
            progressPaint
        )
    }

    override fun setAlpha(alpha: Int) {
        bgPaint.alpha = alpha
        progressPaint.alpha = alpha
        invalidateSelf()
    }

    override fun setColorFilter(colorFilter: ColorFilter?) {
        bgPaint.colorFilter = colorFilter
        progressPaint.colorFilter = colorFilter
        invalidateSelf()
    }

    override fun getOpacity(): Int = PixelFormat.TRANSLUCENT
}

使用方式

在代码中给ProgressBar设置该自定义Drawable即可:

val progressDrawable = RoundedCircularProgressDrawable(
    bgColor = ContextCompat.getColor(context, R.color.base_dark),
    progressColor = ContextCompat.getColor(context, R.color.secundary_10),
    strokeWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10f, resources.displayMetrics)
)
findViewById<ProgressBar>(R.id.progress_bar).progressDrawable = progressDrawable
// 更新进度 0.6f对应60%进度
progressDrawable.progress = 0.6f

如果需要保留原有径向渐变效果,给progressPaint设置对应Shader即可,无需修改其他逻辑。


内容的提问来源于stack exchange,提问作者Bogdan Andreica

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 05:00:04