Zum Aktualisieren nach unten ziehen

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

API-Oberfläche

Verwenden Sie die zusammensetzbare Funktion PullToRefreshBox, um „Pull-to-Refresh“ zu implementieren. Sie dient als Container für Ihre scrollbaren Inhalte. Die folgenden wichtigen Parameter steuern das Aktualisierungsverhalten und das Aussehen:

  • 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 initiiert.
  • indicator: Passt den Indikator an, den das System beim Ziehen zum Aktualisieren zeichnet.

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 ist der scrollbare Inhalt.

Ergebnis

In diesem Video wird die grundlegende Pull-to-Refresh-Implementierung aus dem vorherigen Code gezeigt:

Abbildung 1. Eine einfache Pull-to-Refresh-Implementierung für eine Liste von Elementen.

Erweitertes Beispiel: Indikatorfarbe 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 Indikatorfarbe wird über die Eigenschaften containerColor und color im Parameter indicator angepasst.
  • rememberPullToRefreshState() verwaltet den Status der Aktualisierungsaktion. Sie verwenden diesen Status in Verbindung mit dem Parameter indicator.

Ergebnis

In diesem Video wird eine Implementierung von „Zum Aktualisieren ziehen“ mit einem farbigen Indikator gezeigt:

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

Erweitertes Beispiel: Vollständig benutzerdefinierten Indikator erstellen

Sie können komplexe benutzerdefinierte Indikatoren erstellen, indem Sie vorhandene Composables und Animationen nutzen.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 eine benutzerdefinierte Indicator-Composable-Funktion mit dem Namen MyCustomIndicator erstellt. In dieser Composable-Funktion übernimmt der Modifier pullToRefreshIndicator die Positionierung und das Auslösen einer Aktualisierung.
  • Wie im vorherigen Snippet wird im Beispiel die PullToRefreshState-Instanz extrahiert, sodass Sie dieselbe Instanz sowohl an PullToRefreshBox als auch an pullToRefreshModifier übergeben können.
  • Im Beispiel werden die Containerfarbe und der Positionsschwellenwert aus der Klasse PullToRefreshDefaults verwendet. So können Sie das Standardverhalten und die Standardformatierung aus der Material-Bibliothek wiederverwenden und nur die Elemente anpassen, die Sie interessieren.
  • MyCustomIndicator verwendet Crossfade, um zwischen einem Cloud-Symbol und einem CircularProgressIndicator zu wechseln. Das Cloud-Symbol wird größer, wenn der Nutzer zieht, und geht in ein CircularProgressIndicator über, wenn die Aktualisierung beginnt.
    • targetState verwendet isRefreshing, um zu bestimmen, welcher Status angezeigt werden soll (das Cloud-Symbol 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. Der Wert reicht von 0f (kein Ziehen) bis 1f (vollständig gezogen).
    • Mit dem Modifikator graphicsLayer werden Skalierung und Transparenz geändert.

Ergebnis

In diesem Video sehen Sie den benutzerdefinierten Indikator aus dem vorherigen Code:

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

Zusätzliche Ressourcen