Wskaźniki postępu

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

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

  • Ładowanie treści: podczas pobierania treści z sieci, np. wczytywania obrazu lub danych do profilu użytkownika.
  • Przesyłanie pliku: podaj użytkownikowi informacje o tym, ile czasu może potrwać przesyłanie.
  • Długie przetwarzanie: gdy aplikacja przetwarza dużą ilość danych, powinna poinformować użytkownika, jak duży jest postęp przetwarzania.

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

  • Określ: pokazuje, jak duży postęp został osiągnięty.
  • Nieokreślony: animacja jest nieustanna i nie uwzględnia postępu.

Wskaźnik postępu może też wyświetlać się na dwa sposoby:

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

Interfejs API

Chociaż do tworzenia wskaźników postępu zgodnych z Material Design można używać różnych komponentów, ich parametry nie różnią się znacząco. Oto najważniejsze parametry, o których należy pamiętać:

  • progress: bieżący postęp wyświetlany na wskaźniku. Przekaż wartość Float z zakresu 0.01.0.
  • color: kolor rzeczywistego wskaźnika. Jest to część komponentu, która odzwierciedla postęp i obejmuje go w całości po jego zakończeniu.
  • trackColor: kolor ścieżki, na której rysowany jest wskaźnik.

Wskaźniki determinacji

Określony wskaźnik dokładnie odzwierciedla stopień ukończenia działania. Użyj elementów kompozycyjnych LinearProgressIndicator lub CircularProgressIndicator i przekaż wartość parametru progress.

Poniżej znajdziesz stosunkowo szczegółowy przykład. Gdy użytkownik naciśnie przycisk, aplikacja wyświetli wskaźnik postępu i uruchomi coroutine, która stopniowo zwiększa wartość zmiennej progress. W efekcie 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)
    }
}

Jeśli wczytywanie zostało częściowo ukończone, wskaźnik liniowy z poprzedniego przykładu wygląda tak:

Wskaźnik okrągły wygląda tak:

Wskaźniki nieokreślone

Wskaźnik nieokreślony nie wskazuje, jak blisko jest operacja do zakończenia. Zamiast tego używa ruchu, aby poinformować użytkownika, że przetwarzanie jest w toku, ale nie określa stopnia jego zaawansowania.

Aby utworzyć nieokreślony wskaźnik postępu, użyj funkcji kompozycyjnej LinearProgressIndicator lub CircularProgressIndicator, ale nie przekazuj wartości progress. Ten przykład pokazuje, jak można włączyć lub wyłączyć wskaźnik nieokreśloności 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 implementacji, ale z użyciem LinearProgressIndicator zamiast CircularProgressIndicator.

Dodatkowe materiały