Wskaźniki postępu

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

Oto 3 przykłady użycia wskaźnika postępu:

  • Wczytywanie treści: podczas pobierania treści z sieci, np. wczytywania obrazu lub danych profilu użytkownika.
  • Przesyłanie pliku: informuj użytkownika, ile czasu może zająć przesyłanie.
  • Długie przetwarzanie: gdy aplikacja przetwarza dużą ilość danych, informuj użytkownika, jaka część całości została już przetworzona.

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

  • Określony: pokazuje dokładny postęp.
  • Nieokreślony: animacja jest odtwarzana w sposób ciągły, niezależnie od postępu.

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

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

API Surface

Istnieje kilka funkcji kompozycyjnych, których możesz użyć do tworzenia wskaźników postępu zgodnych z Material Design, ale ich parametry nie różnią się zbytnio. Do najważniejszych parametrów, o których należy pamiętać, należą:

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

Wskaźniki określone

Wskaźnik określony dokładnie odzwierciedla stopień ukończenia działania. Użyj funkcji kompozycyjnych LinearProgressIndicator lub CircularProgressIndicator i przekaż wartość parametru progress.

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

@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 ładowanie jest częściowo zakończone, wskaźnik liniowy z poprzedniego przykładu wygląda tak:

Okrągły wskaźnik wygląda tak:

Wskaźniki nieokreślone

Wskaźnik nieokreślony nie pokazuje, jak blisko ukończenia jest operacja. Zamiast tego za pomocą ruchu informuje użytkownika, że przetwarzanie jest w toku, ale nie określa stopnia ukończenia.

Aby utworzyć wskaźnik nieokreślonego postępu, użyj funkcji kompozycyjnej LinearProgressIndicator lub CircularProgressIndicator, ale nie przekazuj wartości dla parametru progress. Poniższy przykład pokazuje, jak przełączać wskaźnik nieokreślony za pomocą 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,
    )
}

Poniżej znajdziesz przykład tej implementacji, gdy wskaźnik jest aktywny:

Poniżej znajdziesz przykład tej samej implementacji, ale z użyciem znaku LinearProgressIndicator zamiast CircularProgressIndicator.

Dodatkowe materiały