'Arc/Semicircle Shape in Jetpack Compose

I'm looking to draw an arc type shape in Jetpack Compose but I'm really struggling to figure out the best way to do it. When I use drawArc, I can't seem to start the arc from the bottom left corner, it just starts from left middle. I've also tried drawRoundRect but I can't find a way to just round the top left and top right corners.

I'll attach a picture, I don't need the white handle within the shape. Desired result:

enter image description here

drawRoundRect attempt:

enter image description here

drawArc attempt:

enter image description here



Solution 1:[1]

You could make it by using a a canvas with your device width but try to increase arc limits beyond device width. With this code

            Canvas(modifier = Modifier.fillMaxSize()) {
                val canvasWidth = size.width
                val canvasHeight = size.height
                val formWidth = (canvasWidth * 2)
                val xPos = canvasWidth / 2

                drawArc(
                    Color.Black,
                    0f,
                    -180f,
                    useCenter = true,
                    size = Size(formWidth, 600f),
                    topLeft = Offset(x = -xPos, y = canvasHeight - 300)
                )
            }

Arc at bottom looks like this:

enter image description here

more info

Solution 2:[2]

You can draw it like this

Placed it to center for demonstration and border is to show that it doesn't overflow Canvas, if you don't pay attention, Canvas draws out of its borders unless use Modifier.clipbounds() is used on Canvas Modifier.

Trick for drawing half arc is to set two times of Canvas height, since arc is drawn inside a rectangle in principle. Changind height of Modifier of canvas changes height of arc.

        Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
            Canvas(
                modifier = Modifier
                    .border(2.dp, Color.Red)
                    .fillMaxWidth()
                    .height(80.dp),
            ) {

                val canvasWidth = size.width
                val canvasHeight = size.height

                drawArc(
                    Color.Blue,
                    startAngle = 180f,
                    sweepAngle = 180f,
                    useCenter = true,
                    size = Size(canvasWidth, 2 * canvasHeight)
                )

                val handleWidth = 200f
                val handleHeight = 30f

                drawRoundRect(
                    Color.White,
                    size = Size(handleWidth, handleHeight),
                    cornerRadius = CornerRadius(5.dp.toPx(), 5.dp.toPx()),
                    topLeft = Offset((canvasWidth - handleWidth) / 2, (canvasHeight - handleHeight)/2)
                )

            }
        }

Result

You can check this tutorial about Jetpack Compose which covers Canvas operations in detail.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Thracian