0

I want to make circular intermediate progress bar in jetpack compose. I tried some piece of code but it's not working correctly to animate the circle. I tried this answer as well, but nothing works

           val strokeWidth = dimensionResource(R.dimen.stroke)
           Box(modifier = Modifier.fillMaxSize()) {
            CircularProgressIndicator(
                progress = .25f,
                modifier = Modifier
                    .align(Alignment.Center)
                    .drawBehind {
                        drawCircle(
                            Cloudy,
                            radius = size.width / 2 - strokeWidth.toPx() / 2,
                            style = Stroke(strokeWidth.toPx())
                        )
                    },
                color = Aqua,
                strokeWidth = strokeWidth
             )
          }
            

Actual Output

The animation is not working

enter image description here

Expected Output

enter image description here

Kotlin Learner
  • 3,995
  • 6
  • 47
  • 127

1 Answers1

3

In your case you want an infinite transition animating the arc of circle.
You can draw the arc using drawArc and then rotate it using:

rotate(value) {
  // content is rotated by angle in degrees
}

Something like:

val transition = rememberInfiniteTransition()
val currentRotation by transition.animateValue(
    0F,
    targetValue = 360F,
    Float.VectorConverter,
    infiniteRepeatable(
        animation = tween(
            durationMillis = 5000,
            easing = LinearEasing
        )
    )
)


Box(modifier = Modifier
        .size(100.dp)
        .drawBehind {

            //background fixed circle
            drawCircle(
                color = LightGray,
                radius = size.width / 2 - strokeWidth.toPx() / 2,
                style = Stroke(strokeWidth.toPx())
            )

            val diameterOffset = strokeWidth.toPx() / 2
            val arcDimen = size.width - 2 * diameterOffset

            //arc with indeterminate animation
            rotate(currentRotation) {
                drawArc(
                    color = Red,
                    startAngle = 45F,
                    sweepAngle = 90F,
                    useCenter = false,
                    topLeft = Offset(diameterOffset, diameterOffset),
                    size = Size(arcDimen, arcDimen),
                    style = Stroke(strokeWidth.toPx())
                )
            }
        }

)

enter image description here

Gabriele Mariotti
  • 320,139
  • 94
  • 887
  • 841
  • thank you so much. It works. I have some doubt `topLeft = Offset(diameterOffset, diameterOffset),` what does it do? why we set `offset`? – Kotlin Learner Jan 12 '23 at 16:58
  • @VivekModi In this way you remove half the stroke width from the total diameter for both sides to have a rect with edges that line up with the midpoint of the stroke of the background circle. – Gabriele Mariotti Jan 13 '23 at 06:32
  • Thank you so much. Can you please help me on this [issue](https://stackoverflow.com/q/75112301/8266651) – Kotlin Learner Jan 13 '23 at 21:46