Wskaźniki postępu

Wskaźniki postępu wizualnie przedstawiają stan operacji. Wykorzystują ruch, aby zwrócić uwagę użytkownika na to, jak blisko zakończenia jest proces, np. wczytywanie lub przetwarzanie danych. Mogą też oznaczać, że przetwarzanie jest w toku, bez odniesienia do tego, jak blisko jest zakończenia.

Oto 3 przypadki użycia, w których możesz wykorzystać wskaźnik postępu:

  • Wczytywanie treści: podczas pobierania treści z sieci, np. wczytywania obrazu lub danych profilu użytkownika.
  • Przesyłanie pliku: poinformuj użytkownika, jak długo może potrwać przesyłanie.
  • Długie przetwarzanie: gdy aplikacja przetwarza dużą ilość danych, poinformuj użytkownika, jaka część procesu została już ukończona.

W Material Design są 2 rodzaje wskaźników postępu:

  • Określony: pokazuje dokładnie, jaki postęp został osiągnięty.
  • Nieokreślony: animacja jest odtwarzana w pętli bez względu na postęp.

Wskaźnik postępu może mieć jedną z tych 2 form:

  • Liniowy: poziomy pasek, który wypełnia się od lewej do prawej.
  • Okrągły: okrąg, którego obrys wydłuża się, aż obejmie cały obwód.
Liniowy wskaźnik postępu obok kołowego wskaźnika postępu.
Rysunek 1. Dwa rodzaje wskaźników postępu.

Interfejs API

Chociaż istnieje kilka funkcji kompozycyjnych, których możesz użyć do utworzenia wskaźników postępu zgodnych z Material Design, ich parametry nie różnią się znacząco. Oto kilka kluczowych parametrów, o których warto pamiętać:

  • progress: bieżący postęp wyświetlany przez wskaźnik. Przekaż Float z zakresu od 0.0 do 1.0.
  • color: kolor wskaźnika. Jest to część komponentu, która odzwierciedla postęp i która całkowicie obejmuje komponent po zakończeniu postępu.
  • trackColor: kolor ścieżki, na której jest rysowany wskaźnik.

Wskaźniki określone

Wskaźnik określony dokładnie odzwierciedla stopień ukończenia działania. Użyj funkcji kompozycyjnej 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ółprogram, który stopniowo zwiększa wartość progress. Spowoduje to, że wskaźnik postępu będzie się zwiększał.

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

Gdy wczytywanie jest częściowo ukończone, wskaźnik liniowy z poprzedniego przykładu wygląda tak:

Podobnie wygląda okrągły wskaźnik:

Wskaźniki nieokreślone

Wskaźnik nieokreślony nie odzwierciedla, jak blisko zakończenia jest operacja. Zamiast tego wykorzystuje ruch, aby poinformować użytkownika, że przetwarzanie jest w toku, ale nie określa stopnia ukończenia.

Aby utworzyć nieokreślony wskaźnik postępu, użyj funkcji kompozycyjnej LinearProgressIndicator lub CircularProgressIndicator, ale nie przekazuj wartości dla progress. Poniższy przykład pokazuje, jak można przełączać wskaźnik nieokreślony za pomocą naciśnięcia 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 takiej implementacji, gdy wskaźnik jest aktywny:

Poniżej znajduje się przykład tej samej implementacji, ale z użyciem LinearProgressIndicator zamiast CircularProgressIndicator.

Dodatkowe materiały