如何为CircularProgressIndicator设置自定义半圆缺口形状?
实现带缺口的半圆进度指示器(基于CircularProgressIndicator)
要实现带缺口的半圆进度样式,不需要完全重写整个视图,可以通过自定义Drawable或者扩展CircularProgressIndicator两种方式来实现,下面是具体方案:
方案一:自定义带缺口的半圆进度Drawable
直接创建一个Drawable,手动绘制带缺口的背景和进度圆弧,完全控制样式:
class GapSemiCircleProgressDrawable : Drawable() { private val paint = Paint(Paint.ANTI_ALIAS_FLAG).apply { style = Paint.Style.STROKE strokeWidth = 12.dpToPx() // 进度条宽度,可自行调整 } private var progress = 0f // 0-1范围的进度值 private val gapAngle = 30f // 缺口角度,按需调整 // 计算半圆起始角度(从下方开始,预留缺口一半的空间) private val startAngle = 180f + gapAngle / 2 // 计算可填充的圆弧角度(半圆减去缺口角度) private val sweepAngle = 180f - gapAngle override fun onDraw(canvas: Canvas) { val bounds = bounds val centerX = bounds.centerX().toFloat() val centerY = bounds.centerY().toFloat() val radius = min(bounds.width(), bounds.height()) / 2f - paint.strokeWidth / 2 // 绘制灰色背景圆弧 paint.color = Color.LTGRAY canvas.drawArc( centerX - radius, centerY - radius, centerX + radius, centerY + radius, startAngle, sweepAngle, false, paint ) // 绘制蓝色进度圆弧 paint.color = Color.BLUE val progressSweep = sweepAngle * progress canvas.drawArc( centerX - radius, centerY - radius, centerX + radius, centerY + radius, startAngle, progressSweep, false, paint ) } // 设置进度(0-1) fun setProgress(progress: Float) { this.progress = progress.coerceIn(0f, 1f) invalidateSelf() } 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 Int.dpToPx(): Float = this * Resources.getSystem().displayMetrics.density }
使用方式
在代码中初始化Drawable并绑定到View,更新进度:
// 初始化Drawable val progressDrawable = GapSemiCircleProgressDrawable() // 绑定到ImageView或自定义View progressImageView.setImageDrawable(progressDrawable) // 更新进度为70% progressDrawable.setProgress(0.7f)
方案二:扩展CircularProgressIndicator复用原有逻辑
如果想复用CircularProgressIndicator的进度动画、属性配置等逻辑,可以直接扩展它,重写绘制时的角度参数:
class GapSemiCircleProgressIndicator @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 ) : CircularProgressIndicator(context, attrs, defStyleAttr) { private val gapAngle = 30f // 缺口角度,按需调整 override fun onDraw(canvas: Canvas) { // 临时替换起始角度和扫过角度,绘制带缺口的半圆 val originalStart = startAngle val originalSweep = sweepAngle startAngle = 180f + gapAngle / 2 sweepAngle = 180f - gapAngle super.onDraw(canvas) // 恢复原有参数,避免影响其他逻辑 startAngle = originalStart sweepAngle = originalSweep } }
使用方式
直接在布局中引用自定义View,通过原有属性配置样式:
<com.yourpackage.GapSemiCircleProgressIndicator android:layout_width="100dp" android:layout_height="100dp" android:progress="70" app:indicatorColor="@color/blue" app:trackColor="@color/light_gray" app:strokeWidth="12dp"/>
两种方案都能实现带缺口的半圆进度效果,进度会自动按比例填充到有效圆弧范围内。如果需要更复杂的样式自定义,优先选择方案一;如果想复用系统控件的现有能力,方案二更高效。
内容的提问来源于stack exchange,提问作者Avinta
相关产品推荐
相关产品推荐

