Indicatori di avanzamento

Gli indicatori di avanzamento mostrano visivamente lo stato di un'operazione. Utilizzano il movimento per attirare l'attenzione dell'utente su quanto manca al completamento del processo, ad esempio il caricamento o l'elaborazione dei dati. Possono anche indicare che l'elaborazione è in corso, senza fare riferimento a quanto manca al completamento.

Considera questi tre casi d'uso in cui potresti utilizzare un indicatore di avanzamento:

  • Caricamento dei contenuti: durante il recupero dei contenuti da una rete, ad esempio il caricamento di un'immagine o di dati per un profilo utente.
  • Caricamento di file: fornisci all'utente un feedback sul tempo necessario per il caricamento.
  • Elaborazione lunga: mentre un'app elabora una grande quantità di dati, comunica all'utente la percentuale di completamento.

In Material Design esistono due tipi di indicatori di avanzamento:

  • Determinate: mostra esattamente l'avanzamento.
  • Indeterminato: l'animazione viene eseguita continuamente indipendentemente dall'avanzamento.

Analogamente, un indicatore di avanzamento può assumere una delle due forme seguenti:

  • Lineare: una barra orizzontale che si riempie da sinistra a destra.
  • Circolare: un cerchio il cui tratto aumenta di lunghezza fino a coprire l'intera circonferenza.
Un indicatore di avanzamento lineare accanto a un indicatore di avanzamento circolare.
Figura 1. I due tipi di indicatori di avanzamento.

Piattaforma API

Sebbene esistano diversi componibili che puoi utilizzare per creare indicatori di avanzamento coerenti con Material Design, i loro parametri non differiscono molto. Tra i parametri chiave da tenere a mente ci sono i seguenti:

  • progress: l'avanzamento corrente visualizzato dall'indicatore. Passa un Float compreso tra 0.0 e 1.0.
  • color: il colore dell'indicatore effettivo. ovvero la parte del componente che riflette l'avanzamento e che lo comprende completamente quando l'avanzamento è completo.
  • trackColor: il colore della traccia su cui viene disegnato l'indicatore.

Indicatori determinati

Un indicatore definito riflette esattamente il livello di completamento di un'azione. Utilizza i componibili LinearProgressIndicator o CircularProgressIndicator e passa un valore per il parametro progress.

Lo snippet seguente fornisce un esempio relativamente dettagliato. Quando l'utente preme il pulsante, l'app mostra l'indicatore di avanzamento e avvia una coroutine che aumenta gradualmente il valore di progress. In questo modo, l'indicatore di avanzamento aumenta a sua volta.

@Composable
fun LinearDeterminateIndicator() {
    var currentProgress by remember { mutableFloatStateOf(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 il caricamento è parzialmente completato, l'indicatore lineare nell'esempio precedente appare come segue:

Analogamente, l'indicatore circolare viene visualizzato come segue:

Indicatori indeterminati

Un indicatore indeterminato non riflette il livello di completamento di un'operazione, ma utilizza il movimento per indicare all'utente che l'elaborazione è in corso, senza specificare il grado di completamento.

Per creare un indicatore di avanzamento indeterminato, utilizza il componibile LinearProgressIndicator o CircularProgressIndicator, ma non passare un valore per progress. L'esempio seguente mostra come attivare/disattivare un indicatore indeterminato premendo un pulsante.

@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,
    )
}

Di seguito è riportato un esempio di questa implementazione quando l'indicatore è attivo:

Di seguito è riportato un esempio della stessa implementazione, ma con LinearProgressIndicator anziché CircularProgressIndicator.

Risorse aggiuntive