Mit der Komponente SwipeToDismissBox können Nutzer ein Element schließen oder aktualisieren, indem sie es nach links oder rechts wischen.
API-Oberfläche
Verwenden Sie das SwipeToDismissBox-Composable, um Aktionen zu implementieren, die durch Wischgesten ausgelöst werden. Wichtige Parameter:
state: DerSwipeToDismissBoxState-Zustand, der erstellt wurde, um den Wert zu speichern, der durch Berechnungen für das Wischelement erzeugt wird. Wenn dieser Wert erzeugt wird, werden Ereignisse ausgelöst.backgroundContent: Eine anpassbare zusammensetzbare Funktion, die hinter dem Elementinhalt angezeigt wird und sichtbar wird, wenn der Inhalt weggewischt wird.
Einfaches Beispiel: Aktualisieren oder Schließen durch Wischen
Die Snippets in diesem Beispiel zeigen eine Wisch-Implementierung, die das Element entweder aktualisiert, wenn von Anfang bis Ende gewischt wird, oder das Element verwirft, wenn von Ende bis Anfang gewischt wird.
data class TodoItem( val itemDescription: String, var isItemDone: Boolean = false )
@Composable fun TodoListItem( todoItem: TodoItem, onToggleDone: (TodoItem) -> Unit, onRemove: (TodoItem) -> Unit, modifier: Modifier = Modifier, ) { val swipeToDismissBoxState = rememberSwipeToDismissBoxState( confirmValueChange = { if (it == StartToEnd) onToggleDone(todoItem) else if (it == EndToStart) onRemove(todoItem) // Reset item when toggling done status it != StartToEnd } ) SwipeToDismissBox( state = swipeToDismissBoxState, modifier = modifier.fillMaxSize(), backgroundContent = { when (swipeToDismissBoxState.dismissDirection) { StartToEnd -> { Icon( if (todoItem.isItemDone) Icons.Default.CheckBox else Icons.Default.CheckBoxOutlineBlank, contentDescription = if (todoItem.isItemDone) "Done" else "Not done", modifier = Modifier .fillMaxSize() .background(Color.Blue) .wrapContentSize(Alignment.CenterStart) .padding(12.dp), tint = Color.White ) } EndToStart -> { Icon( imageVector = Icons.Default.Delete, contentDescription = "Remove item", modifier = Modifier .fillMaxSize() .background(Color.Red) .wrapContentSize(Alignment.CenterEnd) .padding(12.dp), tint = Color.White ) } Settled -> {} } } ) { ListItem( headlineContent = { Text(todoItem.itemDescription) }, supportingContent = { Text("swipe me to update or remove.") } ) } }
Wichtige Punkte zum Code
swipeToDismissBoxStateverwaltet den Komponentenstatus. DerconfirmValueChange-Callback wird ausgelöst, sobald die Interaktion mit dem Element abgeschlossen ist. Der Callback-Text verarbeitet die verschiedenen möglichen Aktionen. Der Callback gibt einen booleschen Wert zurück, der der Komponente mitteilt, ob eine Schließanimation angezeigt werden soll. In diesem Fall:- Wenn das Element von Anfang bis Ende gewischt wird, wird der
onToggleDone-Lambda-Ausdruck aufgerufen und der aktuelletodoItemübergeben. Dies entspricht dem Aktualisieren des To-do-Elements. - Wenn das Element von rechts nach links gewischt wird, wird das Lambda
onRemoveaufgerufen und das aktuelletodoItemübergeben. Dies entspricht dem Löschen des To-Do-Elements. it != StartToEnd: Diese Zeile gibttruezurück, wenn die Wischrichtung nichtStartToEndist, andernfallsfalse. Wennfalsezurückgegeben wird, wird verhindert, dass dieSwipeToDismissBoxnach einer Wischgeste zum Ein- oder Ausschalten sofort verschwindet. So kann eine visuelle Bestätigung oder Animation angezeigt werden.
- Wenn das Element von Anfang bis Ende gewischt wird, wird der
SwipeToDismissBoxermöglicht horizontales Wischen für jedes Element. Im Ruhezustand wird der innere Inhalt der Komponente angezeigt. Wenn ein Nutzer jedoch mit dem Wischen beginnt, wird der Inhalt wegbewegt und diebackgroundContentwird angezeigt. Sowohl der normale Inhalt als auch derbackgroundContenterhalten die vollständigen Einschränkungen des übergeordneten Containers, in dem sie gerendert werden sollen.contentwird überbackgroundContentgezeichnet. In diesem Fall:backgroundContentwird alsIconmit einer Hintergrundfarbe basierend aufSwipeToDismissBoxValueimplementiert:Bluebeim Wischen nachStartToEnd– eine Aufgabe umschalten.Redbeim Wischen vonEndToStart– Löschen eines To-do-Elements.- Für
Settledwird im Hintergrund nichts angezeigt. Wenn das Element nicht gewischt wird, wird im Hintergrund nichts angezeigt. - Auch die angezeigte
Iconpasst sich der Wischrichtung an: StartToEndzeigt das SymbolCheckBoxan, wenn die Aufgabe erledigt ist, und das SymbolCheckBoxOutlineBlank, wenn sie nicht erledigt ist.- Für
EndToStartwird das SymbolDeleteangezeigt.
@Composable private fun SwipeItemExample() { val todoItems = remember { mutableStateListOf( TodoItem("Pay bills"), TodoItem("Buy groceries"), TodoItem("Go to gym"), TodoItem("Get dinner") ) } LazyColumn { items( items = todoItems, key = { it.itemDescription } ) { todoItem -> TodoListItem( todoItem = todoItem, onToggleDone = { todoItem -> todoItem.isItemDone = !todoItem.isItemDone }, onRemove = { todoItem -> todoItems -= todoItem }, modifier = Modifier.animateItem() ) } } }
Wichtige Punkte zum Code
mutableStateListOf(...)erstellt eine beobachtbare Liste, dieTodoItem-Objekte enthalten kann. Wenn ein Element zu dieser Liste hinzugefügt oder daraus entfernt wird, werden die davon abhängigen Teile der Benutzeroberfläche von Compose neu zusammengesetzt.- In
mutableStateListOf()werden vierTodoItem-Objekte mit den entsprechenden Beschreibungen initialisiert: „Rechnungen bezahlen“, „Lebensmittel kaufen“, „Ins Fitnessstudio gehen“ und „Abendessen holen“.
- In
LazyColumnzeigt eine vertikal scrollbare Liste vontodoItemsan.onToggleDone = { todoItem -> ... }ist eine Callback-Funktion, die inTodoListItemaufgerufen wird, wenn der Nutzer ein Objekt als erledigt markiert. Das AttributisItemDonedertodoItemwird aktualisiert. DatodoItemseinmutableStateListOfist, löst diese Änderung eine Neuzusammensetzung aus, wodurch die Benutzeroberfläche aktualisiert wird.onRemove = { todoItem -> ... }ist eine Callback-Funktion, die ausgelöst wird, wenn der Nutzer den Artikel entfernt. Dadurch wird die spezifischetodoItemaus der ListetodoItemsentfernt. Dies führt auch zu einer Neuzusammensetzung und das Element wird aus der angezeigten Liste entfernt.- Auf jedes
TodoListItem-Element wird einanimateItem-Modifikator angewendet, sodass derplacementSpec-Modifikator aufgerufen wird, wenn das Element geschlossen wurde. Dadurch wird das Entfernen des Elements sowie die Neuanordnung anderer Elemente in der Liste animiert.
Ergebnis
Das folgende Video zeigt die grundlegende Funktion „Zum Schließen wischen“ aus den vorherigen Snippets:
Den vollständigen Beispielcode finden Sie in der GitHub-Quelldatei.
Erweitertes Beispiel: Hintergrundfarbe beim Wischen animieren
In den folgenden Snippets wird gezeigt, wie Sie einen Positionsschwellenwert einbinden, um die Hintergrundfarbe eines Elements beim Wischen zu animieren.
data class TodoItem( val itemDescription: String, var isItemDone: Boolean = false )
@Composable fun TodoListItemWithAnimation( todoItem: TodoItem, onToggleDone: (TodoItem) -> Unit, onRemove: (TodoItem) -> Unit, modifier: Modifier = Modifier, ) { val swipeToDismissBoxState = rememberSwipeToDismissBoxState( confirmValueChange = { if (it == StartToEnd) onToggleDone(todoItem) else if (it == EndToStart) onRemove(todoItem) // Reset item when toggling done status it != StartToEnd } ) SwipeToDismissBox( state = swipeToDismissBoxState, modifier = modifier.fillMaxSize(), backgroundContent = { when (swipeToDismissBoxState.dismissDirection) { StartToEnd -> { Icon( if (todoItem.isItemDone) Icons.Default.CheckBox else Icons.Default.CheckBoxOutlineBlank, contentDescription = if (todoItem.isItemDone) "Done" else "Not done", modifier = Modifier .fillMaxSize() .drawBehind { drawRect(lerp(Color.LightGray, Color.Blue, swipeToDismissBoxState.progress)) } .wrapContentSize(Alignment.CenterStart) .padding(12.dp), tint = Color.White ) } EndToStart -> { Icon( imageVector = Icons.Default.Delete, contentDescription = "Remove item", modifier = Modifier .fillMaxSize() .background(lerp(Color.LightGray, Color.Red, swipeToDismissBoxState.progress)) .wrapContentSize(Alignment.CenterEnd) .padding(12.dp), tint = Color.White ) } Settled -> {} } } ) { OutlinedCard(shape = RectangleShape) { ListItem( headlineContent = { Text(todoItem.itemDescription) }, supportingContent = { Text("swipe me to update or remove.") } ) } } }
Wichtige Punkte zum Code
drawBehindzeichnet direkt in den Canvas hinter dem Inhalt desIcon-Kompositionselements.drawRect()zeichnet ein Rechteck auf dem Canvas und füllt die gesamten Grenzen des Zeichenbereichs mit dem angegebenenColor.
- Beim Wischen wird die Hintergrundfarbe des Elements mithilfe von
lerpfließend geändert.- Bei einem Wischen von
StartToEndändert sich die Hintergrundfarbe allmählich von Hellgrau zu Blau. - Bei einer Wischgeste von
EndToStartändert sich die Hintergrundfarbe allmählich von Hellgrau zu Rot. - Der Übergang von einer Farbe zur nächsten wird durch
swipeToDismissBoxState.progressbestimmt.
- Bei einem Wischen von
OutlinedCardfügt eine subtile visuelle Trennung zwischen den Listenelementen hinzu.
@Composable private fun SwipeItemWithAnimationExample() { val todoItems = remember { mutableStateListOf( TodoItem("Pay bills"), TodoItem("Buy groceries"), TodoItem("Go to gym"), TodoItem("Get dinner") ) } LazyColumn { items( items = todoItems, key = { it.itemDescription } ) { todoItem -> TodoListItemWithAnimation( todoItem = todoItem, onToggleDone = { todoItem -> todoItem.isItemDone = !todoItem.isItemDone }, onRemove = { todoItem -> todoItems -= todoItem }, modifier = Modifier.animateItem() ) } } }
Wichtige Punkte zum Code
- Wichtige Informationen zu diesem Code finden Sie im vorherigen Abschnitt unter Wichtige Punkte. Dort wird ein identisches Code-Snippet beschrieben.
Ergebnis
Das folgende Video zeigt die erweiterte Funktionalität mit animierter Hintergrundfarbe:
Den vollständigen Beispielcode finden Sie in der GitHub-Quelldatei.