I know I can have a CircularProgressIndicator
to indicate some progress, but can I also give it a custom shape like this:
The goal would be a semi circle with some left out elements but still would fill correctly. I think I need to write some custom view for the "100%" progress part, but how to get the custom drawable for this?
You can use this as a starting point for the custom view. Depending on the requirement you can modify the values to get the desired UI.
class MyCircularProgressView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyle: Int = 0,
) : View(context, attrs, defStyle) {
private var stroke = 25F
var size: Int = 200
set(value) {
field = value
stroke = value * 0.125F
invalidate()
}
var backgroundStartAngle: Float = 30F
set(value) {
field = value
invalidate()
}
var backgroundSweepAngle: Float = 300F
set(value) {
field = value
invalidate()
}
var progressStartAngle: Float = 150F
set(value) {
field = value
invalidate()
}
var progressSweepAngle: Float = 180F
set(value) {
field = value
invalidate()
}
private val backgroundPaint = Paint()
private val progressPaint = Paint()
init {
context.theme.obtainStyledAttributes(attrs, R.styleable.MyCircularProgressView, 0, 0).apply {
try {
// Handle attributes passed from XMl here
} finally {
recycle()
}
}
backgroundPaint.apply {
color = 0xFFE0E0E0.toInt()
strokeCap = Paint.Cap.ROUND
style = Paint.Style.STROKE
strokeWidth = stroke
}
progressPaint.apply {
color = 0xFF0000EE.toInt()
strokeCap = Paint.Cap.ROUND
style = Paint.Style.STROKE
strokeWidth = stroke
}
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
canvas.drawArc(
stroke / 2F,
stroke / 2F,
size.toFloat(),
size.toFloat(),
backgroundStartAngle % 360F,
backgroundSweepAngle % 360F,
false,
backgroundPaint,
)
canvas.drawArc(
stroke / 2F,
stroke / 2F,
size.toFloat(),
size.toFloat(),
progressStartAngle % 360F,
progressSweepAngle % 360F,
false,
progressPaint,
)
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
setMeasuredDimension(size + stroke.toInt(), size + stroke.toInt())
}
}
Output UI