Indicadores de progresso

Os indicadores de progresso mostram visualmente o status de uma operação. Eles usam o movimento para informar ao usuário se o processo está próximo da conclusão, como carregar ou processar dados. Eles também podem indicar que o processamento está ocorrendo, sem referência ao quão próximo ele pode estar para a conclusão.

Considere estes três casos de uso em que é possível usar um indicador de progresso:

  • Carregar conteúdo: ao buscar conteúdo de uma rede, por exemplo, ao carregar uma imagem ou dados para um perfil de usuário.
  • Upload de arquivo: forneça feedback ao usuário sobre a duração do upload.
  • Processamento longo: enquanto o app estiver processando uma grande quantidade de dados, transmita ao usuário quanto do total foi concluído.

No Material Design, há dois tipos de indicador de progresso:

  • Determinado: mostra exatamente quanto progresso foi feito.
  • Indeterminado: a animação é contínua, sem considerar o progresso.

Da mesma forma, um indicador de progresso pode assumir uma das duas formas a seguir:

  • Linear: uma barra horizontal que é preenchida da esquerda para a direita.
  • Circular: um círculo cujo traço cresce em comprimento até abranger toda a circunferência.
Um indicador de progresso linear ao lado de um indicador de progresso circular.
Figura 1. Os dois tipos de indicadores de progresso.

Plataforma da API

Embora existam vários elementos combináveis que podem ser usados para criar botões de ação flutuantes consistentes com o Material Design, os parâmetros deles não são muito diferentes. Entre os parâmetros-chave que você deve ter em mente estão:

  • progress: o progresso atual que o indicador mostra. Transmita um Float entre 0.0 e 1.0.
  • color: a cor do indicador real. Ou seja, a parte do componente que reflete o progresso e que abrange totalmente o componente quando o progresso é concluído.
  • trackColor: a cor da faixa sobre a qual o indicador é desenhado.

Determinação de indicadores

Um indicador determinado reflete exatamente a conclusão de uma ação. Use os elementos combináveis LinearProgressIndicator ou CircularProgressIndicator e transmita um valor para o parâmetro progress.

O snippet a seguir oferece um exemplo relativamente detalhado. Quando o usuário pressiona o botão, o app mostra o indicador de progresso e inicia uma corrotina que aumenta gradualmente o valor de progress. Isso faz com que o indicador de progresso seja iterado por vez.

@Composable
fun LinearDeterminateIndicator() {
    var currentProgress by remember { mutableStateOf(0f) }
    var loading by remember { mutableStateOf(false) }
    val scope = rememberCoroutineScope() // Create a coroutine scope

    Column(
        verticalArrangement = Arrangement.spacedBy(12.dp),
        horizontalAlignment = Alignment.CenterHorizontally,
        modifier = Modifier.fillMaxWidth()
    ) {
        Button(onClick = {
            loading = true
            scope.launch {
                loadProgress { progress ->
                    currentProgress = progress
                }
                loading = false // Reset loading when the coroutine finishes
            }
        }, enabled = !loading) {
            Text("Start loading")
        }

        if (loading) {
            LinearProgressIndicator(
                progress = { currentProgress },
                modifier = Modifier.fillMaxWidth(),
            )
        }
    }
}

/** Iterate the progress value */
suspend fun loadProgress(updateProgress: (Float) -> Unit) {
    for (i in 1..100) {
        updateProgress(i.toFloat() / 100)
        delay(100)
    }
}

Quando o carregamento é parcialmente concluído, o indicador linear no exemplo anterior aparece da seguinte maneira:

Da mesma forma, o indicador circular aparece da seguinte forma:

Indicadores indeterminados

Um indicador indeterminado não reflete o tempo de conclusão de uma operação. Em vez disso, ele usa movimento para indicar ao usuário que o processamento está em andamento, mas sem especificar nenhum grau de conclusão.

Para criar um indicador de progresso indeterminado, use o elemento combinável LinearProgressIndicator ou CircularProgressIndicator, mas não transmita um valor para progress. O exemplo a seguir demonstra como ativar ou desativar um indicador indeterminado ao pressionar um botão.

@Composable
fun IndeterminateCircularIndicator() {
    var loading by remember { mutableStateOf(false) }

    Button(onClick = { loading = true }, enabled = !loading) {
        Text("Start loading")
    }

    if (!loading) return

    CircularProgressIndicator(
        modifier = Modifier.width(64.dp),
        color = MaterialTheme.colorScheme.secondary,
        trackColor = MaterialTheme.colorScheme.surfaceVariant,
    )
}

Confira a seguir um exemplo dessa implementação quando o indicador está ativo:

Confira abaixo um exemplo da mesma implementação, mas com LinearProgressIndicator em vez de CircularProgressIndicator.

Outros recursos