Przeciągnij w dół, aby odświeżyć

Komponent „przeciągnij, aby odświeżyć” umożliwia użytkownikom przeciąganie w dół na początku treści aplikacji, aby odświeżyć dane.

Interfejs API

Aby wdrożyć funkcję odświeżania przez przeciąganie, która działa jako element zawierający przewijane treści, użyj komponentu PullToRefreshBox. Te kluczowe parametry określają zachowanie i wygląd odświeżania:

  • isRefreshing: wartość logiczna wskazująca, czy działanie odświeżania jest w toku.
  • onRefresh: funkcja lambda, która jest wykonywana, gdy użytkownik inicjuje odświeżanie.
  • indicator: umożliwia dostosowanie wskaźnika, który system wyświetla podczas przeciągania w celu odświeżenia.

Przykład podstawowy

Ten fragment kodu pokazuje podstawowe zastosowanie funkcji PullToRefreshBox:

@Composable
fun PullToRefreshBasicSample(
    items: List<String>,
    isRefreshing: Boolean,
    onRefresh: () -> Unit,
    modifier: Modifier = Modifier
) {
    PullToRefreshBox(
        isRefreshing = isRefreshing,
        onRefresh = onRefresh,
        modifier = modifier
    ) {
        LazyColumn(Modifier.fillMaxSize()) {
            items(items) {
                ListItem({ Text(text = it) })
            }
        }
    }
}

Najważniejsze informacje o kodzie

  • PullToRefreshBox zawiera element LazyColumn, który wyświetla listę napisów.
  • PullToRefreshBox wymaga parametrów isRefreshingonRefresh.
  • Treści w bloku PullToRefreshBox stanowią przewijaną treść.

Wynik

Ten film pokazuje podstawową implementację funkcji odświeżania przez pociągnięcie z poprzedniego kodu:

Rysunek 1. Podstawowa implementacja funkcji odświeżania przez pociągnięcie na liście elementów.

Przykład zaawansowany: dostosowywanie koloru wskaźnika

@Composable
fun PullToRefreshCustomStyleSample(
    items: List<String>,
    isRefreshing: Boolean,
    onRefresh: () -> Unit,
    modifier: Modifier = Modifier
) {
    val state = rememberPullToRefreshState()

    PullToRefreshBox(
        isRefreshing = isRefreshing,
        onRefresh = onRefresh,
        modifier = modifier,
        state = state,
        indicator = {
            Indicator(
                modifier = Modifier.align(Alignment.TopCenter),
                isRefreshing = isRefreshing,
                containerColor = MaterialTheme.colorScheme.primaryContainer,
                color = MaterialTheme.colorScheme.onPrimaryContainer,
                state = state
            )
        },
    ) {
        LazyColumn(Modifier.fillMaxSize()) {
            items(items) {
                ListItem({ Text(text = it) })
            }
        }
    }
}

Najważniejsze informacje o kodzie

  • Kolor wskaźnika jest dostosowywany za pomocą właściwości containerColorcolor w parametrze indicator.
  • rememberPullToRefreshState() określa stan działania odświeżania. Używasz tego stanu w połączeniu z parametrem indicator.

Wynik

Ten film pokazuje implementację funkcji odświeżania przez pociągnięcie z kolorowym wskaźnikiem:

Rysunek 2. Implementacja funkcji odświeżania przez pociągnięcie z użyciem stylu niestandardowego.

Przykład zaawansowany: tworzenie w pełni niestandardowego wskaźnika

Kompleksowe wskaźniki niestandardowe możesz tworzyć, korzystając z dostępnych komponentów i animacji.Ten fragment kodu pokazuje, jak utworzyć w swojej implementacji funkcji przeciągania, aby odświeżyć wskaźnik całkowicie niestandardowy:

@Composable
fun PullToRefreshCustomIndicatorSample(
    items: List<String>,
    isRefreshing: Boolean,
    onRefresh: () -> Unit,
    modifier: Modifier = Modifier
) {
    val state = rememberPullToRefreshState()

    PullToRefreshBox(
        isRefreshing = isRefreshing,
        onRefresh = onRefresh,
        modifier = modifier,
        state = state,
        indicator = {
            MyCustomIndicator(
                state = state,
                isRefreshing = isRefreshing,
                modifier = Modifier.align(Alignment.TopCenter)
            )
        }
    ) {
        LazyColumn(Modifier.fillMaxSize()) {
            items(items) {
                ListItem({ Text(text = it) })
            }
        }
    }
}

// ...
@Composable
fun MyCustomIndicator(
    state: PullToRefreshState,
    isRefreshing: Boolean,
    modifier: Modifier = Modifier,
) {
    Box(
        modifier = modifier.pullToRefreshIndicator(
            state = state,
            isRefreshing = isRefreshing,
            containerColor = PullToRefreshDefaults.containerColor,
            threshold = PositionalThreshold
        ),
        contentAlignment = Alignment.Center
    ) {
        Crossfade(
            targetState = isRefreshing,
            animationSpec = tween(durationMillis = CROSSFADE_DURATION_MILLIS),
            modifier = Modifier.align(Alignment.Center)
        ) { refreshing ->
            if (refreshing) {
                CircularProgressIndicator(Modifier.size(SPINNER_SIZE))
            } else {
                val distanceFraction = { state.distanceFraction.coerceIn(0f, 1f) }
                Icon(
                    imageVector = Icons.Filled.CloudDownload,
                    contentDescription = "Refresh",
                    modifier = Modifier
                        .size(18.dp)
                        .graphicsLayer {
                            val progress = distanceFraction()
                            this.alpha = progress
                            this.scaleX = progress
                            this.scaleY = progress
                        }
                )
            }
        }
    }
}

Najważniejsze informacje o kodzie

  • Poprzedni fragment kodu używał funkcji Indicator udostępnionej przez bibliotekę. Ten fragment kodu tworzy niestandardowy element kompozytowy wskaźnika o nazwie MyCustomIndicator. W tym składanym modyfikator pullToRefreshIndicator odpowiada za pozycjonowanie i uruchamianie odświeżania.
  • Podobnie jak w poprzednim fragmencie kodu przykład wyodrębnia instancję PullToRefreshState, więc możesz przekazać tę samą instancję do funkcji PullToRefreshBoxpullToRefreshModifier.
  • Przykład używa koloru kontenera i progresji położenia z klasy PullToRefreshDefaults. Dzięki temu możesz ponownie użyć domyślnego zachowania i stylu z biblioteki Material, dostosowując tylko te elementy, które Cię interesują.
  • MyCustomIndicator używa Crossfade do przejścia między ikoną chmury a CircularProgressIndicator. Ikona chmury powiększa się, gdy użytkownik ją ciągnie, a przechodzi w postać CircularProgressIndicator, gdy rozpoczyna się działanie odświeżania.
    • Właściwość targetState korzysta z właściwości isRefreshing, aby określić, który stan ma być wyświetlany (ikona chmury lub kołowy wskaźnik postępu).
    • animationSpec definiuje animację tween dla przejścia o określonym czasie trwania CROSSFADE_DURATION_MILLIS.
    • state.distanceFraction reprezentuje odległość, na jaką użytkownik przewinął ekran w dół, od 0f (brak przewijania) do 1f (pełne przewinięcie).
    • Modyfikator graphicsLayer zmienia skalę i przezroczystość.

Wynik

Ten film pokazuje wskaźnik niestandardowy z poprzedniego kodu:

Rysunek 3. Implementacja funkcji odświeżania przez pociągnięcie z niestandardowym wskaźnikiem.

Dodatkowe materiały