CircularProgressIndicator in Jetpack Compose (with Examples)

CircularProgressIndicator Jetpack Compose

In this article, we’ll explore CircularProgressIndicator in Jetpack Compose with the help of examples.

Prerequisites:

For this article, create an empty Jetpack Compose project and open MainActivity. Create a MyUI() composable and call it from the onCreate() method.

// we'll use the following imports
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.rotate
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            YourProjectNameTheme(darkTheme = false) {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colors.background
                ) {
                    Column(
                        modifier = Modifier.fillMaxSize(),
                        verticalArrangement = Arrangement.Center,
                        horizontalAlignment = Alignment.CenterHorizontally
                    ) {
                        MyUI()
                    }
                }
            }
        }
    }
}

@Composable
fun MyUI() {

}

We’ll write our code in the MyUI().

What is Circular Progress Indicator?

Circular progress indicators act like loading spinners. They inform users about the status of ongoing processes, such as loading an app, submitting a form, or saving updates.

There are two types of circular progress indicators – indeterminate and determinate. Let’s look at each one.

1. Indeterminate CircularProgressIndicator:

It runs forever.

@Composable
fun CircularProgressIndicator(
    modifier: Modifier = Modifier,
    color: Color = MaterialTheme.colors.primary,
    strokeWidth: Dp = ProgressIndicatorDefaults.StrokeWidth
)

modifier – It is to change the layout of the progress bar. For example, we set the size using the size() modifier.

color – Indicator’s color.

strokeWidth – indicator’s width (thickness)

Example:

@Composable
fun MyUI() {
    CircularProgressIndicator(
        modifier = Modifier.size(size = 64.dp),
        color = Color.Magenta,
        strokeWidth = 6.dp
    )
}

Output:

Indeterminate Circular Progress Indicator

Related: How to Use Colors in Jetpack Compose?

Adding Text:

We can easily display text using the Text() and Row() composables.

@Composable
fun MyUI() {
    Row(verticalAlignment = Alignment.CenterVertically) {
        CircularProgressIndicator(
            modifier = Modifier.size(size = 28.dp),
            color = Color.Red
        )
        Spacer(modifier = Modifier.width(width = 8.dp))
        Text(text = "Loading...")
    }
}

Output:

Loading Bar with Text

2. Determinate CircularProgressIndicator:

It is similar to the indeterminate indicator but shows progress value instead of running forever.

@Composable
fun CircularProgressIndicator(
    /*@FloatRange(from = 0.0, to = 1.0)*/
    progress: Float,
    modifier: Modifier = Modifier,
    color: Color = MaterialTheme.colors.primary,
    strokeWidth: Dp = ProgressIndicatorDefaults.StrokeWidth
)

The progress value ranges from 0f to 1f. 0f represents no progress, and 1f means 100% progress.

Example:

@Composable
fun MyUI() {
    CircularProgressIndicator(
        progress = 0.6f,
        modifier = Modifier.size(size = 64.dp),
        color = Color.Magenta,
        strokeWidth = 6.dp
    )
}

Output:

Determinate Circular Progress Indicator

Adding Animation:

By default, you don’t see any animation while showing the progress. We can add a smooth animation by using animateFloatAsState API.

@Composable
fun MyUI() {
    // progress value 
    var progress by remember {
        mutableStateOf(0f) // initially 0f
    }

    // animation
    val progressAnimate by animateFloatAsState(
        targetValue = progress,
        animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec
    )

    CircularProgressIndicator(
        progress = progressAnimate,
        modifier = Modifier.size(size = 64.dp),
        color = Color.Magenta,
        strokeWidth = 6.dp
    )

    // this is called when the Activity is launched
    LaunchedEffect(Unit) {
        progress = 0.6f
    }

    // add space between indicator and button
    Spacer(modifier = Modifier.height(height = 16.dp))

    // button
    Button(
        onClick = {
            progress = (0 until 100).random().toFloat() / 100
        },
        colors = ButtonDefaults.buttonColors(
            backgroundColor = Color.Magenta
        )
    ) {
        Text(
            text = "Random",
            color = Color.White
        )
    }
}

Output:

animations indicator

Instead of ProgressAnimationSpec, you can specify other animation spec functions.

By default, the indicator starts at the top center. We can change that by using the modifier’s rotate() function.

@Composable
fun MyUI() {
    CircularProgressIndicator(
        progress = 0.6f,
        modifier = Modifier
            .size(size = 64.dp)
            .rotate(degrees = 45f),
        color = Color.Magenta,
        strokeWidth = 6.dp
    )
}

Output:

Jetpack Compose CircularProgressIndicator rotate

The Progress Indicator API doesn’t offer many customizations. If you want to create your own indicator, use Canvas. Take a look at these beautiful custom progress bars made with Canvas.

This is all about CircularProgressIndicator in Jetpack Compose. I hope you have learned something new. If you have any doubts, comment below.

Related Articles:

References:

Leave a Comment