Zum Aktualisieren nach unten ziehen

Mit der Komponente „Zum Aktualisieren wischen“ können Nutzer am Anfang der App-Inhalte nach unten wischen, um die Daten zu aktualisieren.

API-Oberfläche

Verwenden Sie das PullToRefreshBox-Element, um die Funktion „Zum Aktualisieren ziehen“ zu implementieren, die als Container für scrollbare Inhalte dient. Die folgenden wichtigen Parameter steuern das Aktualisierungsverhalten und das Erscheinungsbild:

  • isRefreshing: Ein boolescher Wert, der angibt, ob die Aktualisierung gerade ausgeführt wird.
  • onRefresh: Eine Lambda-Funktion, die ausgeführt wird, wenn der Nutzer eine Aktualisierung auslöst.
  • indicator: Hiermit wird der Indikator angepasst, der beim Ziehen zum Aktualisieren angezeigt wird.

Einfaches Beispiel

Dieses Snippet zeigt die grundlegende Verwendung von 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) })
            }
        }
    }
}

Wichtige Punkte zum Code

  • PullToRefreshBox umschließt ein LazyColumn, in dem eine Liste von Strings angezeigt wird.
  • Für PullToRefreshBox sind die Parameter isRefreshing und onRefresh erforderlich.
  • Der Inhalt im PullToRefreshBox-Block steht für den scrollbaren Inhalt.

Ergebnis

In diesem Video wird die grundlegende Implementierung der Funktion „Zum Aktualisieren wischen“ aus dem vorherigen Code veranschaulicht:

Abbildung 1. Eine einfache Implementierung von „Zum Aktualisieren wischen“ für eine Liste von Elementen.

Erweitertes Beispiel: Farbe des Indikators anpassen

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

Wichtige Punkte zum Code

  • Die Farbe des Indikators wird über die Eigenschaften containerColor und color im Parameter indicator angepasst.
  • rememberPullToRefreshState() verwaltet den Status der Aktualisierungsaktion. Dieser Status wird in Verbindung mit dem Parameter indicator verwendet.

Ergebnis

In diesem Video wird eine Implementierung des Pull-to-Refresh-Effekts mit einem farbigen Indikator gezeigt:

Abbildung 2. Eine Implementierung des Pull-to-Refresh-Effekts mit einem benutzerdefinierten Stil.

Erweitertes Beispiel: Vollständig benutzerdefinierten Messwert erstellen

Sie können komplexe benutzerdefinierte Indikatoren erstellen, indem Sie vorhandene Composeables und Animationen verwenden.In diesem Snippet wird gezeigt, wie Sie einen vollständig benutzerdefinierten Indikator in Ihrer Pull-to-Refresh-Implementierung erstellen:

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

Wichtige Punkte zum Code

  • Im vorherigen Snippet wurde die von der Bibliothek bereitgestellte Indicator verwendet. Mit diesem Snippet wird ein benutzerdefinierter Indikator-Composeable mit dem Namen MyCustomIndicator erstellt. In diesem Composeable wird die Positionierung und das Auslösen einer Aktualisierung über den Modifikator pullToRefreshIndicator gesteuert.
  • Wie im vorherigen Snippet wurde die PullToRefreshState-Instanz extrahiert, sodass dieselbe Instanz sowohl an PullToRefreshBox als auch an pullToRefreshModifier übergeben werden kann.
  • Die Containerfarbe und der Positionierungsgrenzwert werden aus der Klasse PullToRefreshDefaults verwendet. So können Sie das Standardverhalten und das Standard-Styling aus der Materialbibliothek wiederverwenden und nur die Elemente anpassen, die Sie interessieren.
  • In MyCustomIndicator wird Crossfade verwendet, um zwischen einem Wolkensymbol und einem CircularProgressIndicator zu wechseln. Das Wolkensymbol wird vergrößert, während der Nutzer zieht, und zu einem CircularProgressIndicator, wenn die Aktualisierungsaktion beginnt.
    • targetState verwendet isRefreshing, um festzulegen, welcher Status angezeigt werden soll (das Wolkensymbol oder die kreisförmige Fortschrittsanzeige).
    • animationSpec definiert eine tween-Animation für den Übergang mit einer angegebenen Dauer von CROSSFADE_DURATION_MILLIS.
    • state.distanceFraction gibt an, wie weit der Nutzer nach unten gezogen hat. Die Werte reichen von 0f (nicht gezogen) bis 1f (vollständig herausgezoomt).
    • Mit der Tastenkombination graphicsLayer können Sie die Skalierung und Transparenz ändern.

Ergebnis

In diesem Video wird der benutzerdefinierte Indikator aus dem Code oben gezeigt:

Abbildung 3. Eine Implementierung des Pull-to-Refresh-Prinzips mit einem benutzerdefinierten Indikator.

Weitere Informationen