Android Drawable环形进度条Corners属性不生效问题求助
解决Android环形进度条圆角不生效的问题
你遇到的这个问题其实是Android系统的一个小限制——ring类型的ShapeDrawable不支持<corners>属性,所以你在XML里加的<corners android:radius="8dp"/>完全不会起作用,这不是你的写法错了,是系统本身就不支持这个组合。
要实现带圆角的环形进度条,我们需要换一种方式:用自定义Drawable来绘制,通过Paint的strokeCap属性来实现圆角端点。下面是具体的实现步骤:
1. 自定义带圆角的环形Drawable
创建一个RoundCornerRingDrawable类,通过Canvas绘制带圆角的背景圆环和进度圆弧:
import android.graphics.* import android.graphics.drawable.Drawable import android.util.TypedValue import androidx.core.content.ContextCompat class RoundCornerRingDrawable : Drawable() { private val paint = Paint(Paint.ANTI_ALIAS_FLAG) private var backgroundColor = Color.LTGRAY private var progressColor = Color.GREEN private var strokeWidth = dpToPx(3f) private var progress = 0f // 进度范围0-1 private var cornerRadius = dpToPx(8f) override fun draw(canvas: Canvas) { val bounds = bounds val centerX = bounds.centerX().toFloat() val centerY = bounds.centerY().toFloat() val radius = min(centerX, centerY) - strokeWidth / 2 // 绘制背景圆环 paint.run { color = backgroundColor style = Paint.Style.STROKE strokeWidth = this@RoundCornerRingDrawable.strokeWidth strokeCap = if (cornerRadius > 0) Paint.Cap.ROUND else Paint.Cap.BUTT } canvas.drawCircle(centerX, centerY, radius, paint) // 绘制进度圆弧(从270度开始,和你原来的XML一致) paint.color = progressColor val sweepAngle = progress * 360f canvas.drawArc( centerX - radius, centerY - radius, centerX + radius, centerY + radius, 270f, sweepAngle, false, paint ) } // 以下是Drawable的必填重写方法 override fun setAlpha(alpha: Int) { paint.alpha = alpha invalidateSelf() } override fun setColorFilter(colorFilter: ColorFilter?) { paint.colorFilter = colorFilter invalidateSelf() } override fun getOpacity(): Int = PixelFormat.TRANSLUCENT // 辅助方法:dp转px private fun dpToPx(dp: Float): Float { return TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, dp, resources.displayMetrics ) } // 暴露外部可调用的设置方法 fun setProgress(progress: Float) { this.progress = progress.coerceIn(0f, 1f) // 限制进度在0-1之间 invalidateSelf() } fun setStrokeWidth(dp: Float) { this.strokeWidth = dpToPx(dp) invalidateSelf() } fun setCornerRadius(dp: Float) { this.cornerRadius = dpToPx(dp) invalidateSelf() } fun setColors(backgroundColor: Int, progressColor: Int) { this.backgroundColor = backgroundColor this.progressColor = progressColor invalidateSelf() } }
2. 在代码中使用这个Drawable
在你的Activity或Fragment里,找到对应的View(比如一个普通的View或者ProgressBar),设置这个自定义Drawable作为背景,并配置参数:
// 假设布局里有一个id为round_progress的View val progressView = findViewById<View>(R.id.round_progress) val ringDrawable = RoundCornerRingDrawable().apply { // 设置颜色,替换成你自己的颜色资源 setColors( ContextCompat.getColor(this@MainActivity, R.color.light_grey), ContextCompat.getColor(this@MainActivity, R.color.green) ) setStrokeWidth(3f) // 圆环宽度,对应你原来的3dp setCornerRadius(8f) // 圆角半径,对应你想要的8dp setProgress(0.6f) // 设置60%的进度,范围0-1 } progressView.background = ringDrawable
为什么这个方法能生效?
核心是Paint.Cap.ROUND这个属性——它会把绘制线条的端点变成圆形,当我们绘制圆弧进度时,进度条的两端就会自动呈现圆角效果,完美解决你想要的需求。
如果你需要和原生ProgressBar的进度绑定,也可以基于这个Drawable封装一个自定义ProgressBar,重写onDraw方法,这样就能直接在布局里用android:progress属性来控制进度了。
内容的提问来源于stack exchange,提问作者BVtp
相关产品推荐
相关产品推荐

