Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Circular loading Spinner in jetpack compose

I want to create loading spinner in jetpack compose. I don't have video but I have image how it looks like.

enter image description here

I only know about CircularProgressIndicator but I don't know how to customise and look like above image.

    CircularProgressIndicator(
            progress = progress,
            color = progressColor,
            strokeWidth = strokeWidth,
            modifier = Modifier.fillMaxSize()
    )

Thanks in advance.

UPDATE

I found the video it looks like Twitter loading spinner in web. I made small video screenshot. Please have a look on Youtube

like image 937
Vivek Modi Avatar asked Mar 24 '26 07:03

Vivek Modi


1 Answers

Hello bro try this one and ans me.

@Composable
fun Indicator(
    size: Dp = 32.dp, // indicator size
    sweepAngle: Float = 90f, // angle (lenght) of indicator arc
    color: Color = MaterialTheme.colors.primary, // color of indicator arc line
    strokeWidth: Dp = ProgressIndicatorDefaults.StrokeWidth //width of cicle and ar lines
) {
    ////// animation //////

    // docs recomend use transition animation for infinite loops
    // https://developer.android.com/jetpack/compose/animation
    val transition = rememberInfiniteTransition()

    // define the changing value from 0 to 360.
    // This is the angle of the beginning of indicator arc
    // this value will change over time from 0 to 360 and repeat indefinitely.
    // it changes starting position of the indicator arc and the animation is obtained
    val currentArcStartAngle by transition.animateValue(
        0,
        360,
        Int.VectorConverter,
        infiniteRepeatable(
            animation = tween(
                durationMillis = 1100,
                easing = LinearEasing
            )
        )
    )

    ////// draw /////

    // define stroke with given width and arc ends type considering device DPI
    val stroke = with(LocalDensity.current) {
        Stroke(width = strokeWidth.toPx(), cap = StrokeCap.Square)
    }

    // draw on canvas
    Canvas(
        Modifier
            .progressSemantics() // (optional) for Accessibility services
            .size(size) // canvas size
            .padding(strokeWidth / 2) //padding. otherwise, not the whole circle will fit in the canvas
    ) {
        // draw "background" (gray) circle with defined stroke.
        // without explicit center and radius it fit canvas bounds
        drawCircle(Color.LightGray, style = stroke)

        // draw arc with the same stroke
        drawArc(
            color,
            // arc start angle
            // -90 shifts the start position towards the y-axis
            startAngle = currentArcStartAngle.toFloat() - 90,
            sweepAngle = sweepAngle,
            useCenter = false,
            style = stroke
        )
    }
}

In short - a circle is drawn on the canvas and an indicator arc is drawn on top of it.

transitive animation cycles the value of currentArcStartAngle variable from 0 to 360 (this is the angle in the circle) and this variable is used to set the starting angle of the indicator arc

To better understand what the starting angle, do useCenter = true in drawArc

currentArcStartAngle is State, so each change causes the canvas to be recomposed and redrawn with new start angle

result:

enter image description here

like image 109
vitidev Avatar answered Mar 28 '26 03:03

vitidev



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!