如何为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
相关产品推荐
相关产品推荐

