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ę przeciągania do odświeżenia, która działa jako element sterujący dla treści, których można przewijać, 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: dostosowuje wskaźnik wyświetlany 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ść w bloku PullToRefreshBox to treść przewijana.

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

Korzystając z dostępnych komponentów i animacji, możesz tworzyć złożone wskaźniki niestandardowe.Ten fragment kodu pokazuje, jak utworzyć w swoim komponencie odświeżania przez przeciąganie 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 komponencie modyfikator pullToRefreshIndicator odpowiada za pozycjonowanie i uruchamianie odświeżania.
  • Podobnie jak w poprzednim fragmencie kodu, instancja PullToRefreshState została wyodrębniona, więc tę samą instancję można przekazać do funkcji PullToRefreshBoxpullToRefreshModifier.
  • Kolor kontenera i wartość progowa pozycji są używane 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