Wskaźniki postępu

Wskaźniki postępu informują o stanie operacji. Wykorzystują ruch, aby zwrócić uwagę użytkownika na stopień ukończenia procesu, np. wczytywania lub przetwarzania danych. Mogą też oznaczać, że przetwarzanie już trwa, bez względu na to, jak bardzo zbliża się on do końca.

Rozważ użycie wskaźnika postępu:

  • Wczytywanie treści: podczas pobierania treści z sieci, na przykład wczytywania obrazu lub danych profilu użytkownika.
  • Przesyłanie pliku: poinformuj użytkowników o tym, ile czasu może potrwać przesyłanie.
  • Przetwarzanie długiego czasu przetwarzania: gdy aplikacja przetwarza dużą ilość danych, poinformuj użytkownika, jaka część została już wykonana.

Material Design wyróżnia 2 rodzaje wskaźników postępu:

  • Określ: pokazuje dokładnie postęp osiągnięty.
  • Nieokreślony: animacja odbywa się w sposób ciągły, bez względu na postęp.

Wskaźnik postępu może też wyglądać tak:

  • Liniowy: poziomy pasek, który wypełnia się od lewej do prawej.
  • Okrągły: koło, którego kreska staje się większa, aż obejmie cały okrąg.
Liniowy wskaźnik postępu obok okrągłego wskaźnika postępu.
Rysunek 1. Dwa typy wskaźników postępu.

Przestrzeń API

Chociaż jest kilka elementów kompozycyjnych, których możesz używać do tworzenia pływających przycisków akcji zgodnych ze standardem Material Design, ich parametry nie różnią się znacznie od siebie. Najważniejsze parametry, o których należy pamiętać:

  • progress: bieżący postęp wyświetlany przez wskaźnik. Przekaż Float między 0.0 a 1.0.
  • color: kolor rzeczywistego wskaźnika. To znaczy, że część komponentu, która odzwierciedla postęp i w pełni obejmuje dany element po zakończeniu postępu.
  • trackColor: kolor ścieżki, nad którym rysowany jest wskaźnik.

Określ wskaźniki

Wskaźnik określający dokładnie stopień ukończenia działania. Używaj elementów kompozycyjnych LinearProgressIndicator lub CircularProgressIndicator i przekaż wartość parametru progress.

Poniższy fragment kodu zawiera stosunkowo szczegółowy przykład. Gdy użytkownik naciśnie przycisk, aplikacja wyświetli wskaźnik postępu i uruchomi współpracę, która stopniowo zwiększa wartość progress. Powoduje to, że wskaźnik postępu będzie powtarzał się w kolejnym kroku.

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

Gdy wczytywanie zostanie ukończone, wskaźnik liniowy w poprzednim przykładzie wygląda tak:

Okrąg wygląda też tak:

Nieokreślone wskaźniki

Nieokreślony wskaźnik nie pokazuje, jak blisko ukończenia operacji jest. Wykorzystuje ruch, aby wskazać użytkownikowi, że przetwarzanie już trwa, choć nie określa żadnego stopnia zakończenia.

Aby utworzyć nieokreślony wskaźnik postępu, użyj funkcji kompozycyjnej LinearProgressIndicator lub CircularProgressIndicator, ale nie przekazuj wartości progress. Poniższy przykład pokazuje, jak przełączyć nieokreślony wskaźnik przez naciśnięcie przycisku.

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

Oto przykład implementacji, gdy wskaźnik jest aktywny:

Poniżej znajdziesz przykład implementacji z wykorzystaniem LinearProgressIndicator zamiast CircularProgressIndicator.

Dodatkowe materiały