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
-Element, um Aktionen zu implementieren, die durch Wischbewegungen ausgelöst werden. Zu den wichtigsten Parametern gehören:
state
: DerSwipeToDismissBoxState
-Status, der zum Speichern des durch Berechnungen am Wischelement generierten Werts erstellt wird, wodurch Ereignisse ausgelöst werden.backgroundContent
: Ein anpassbares Element, das hinter dem Artikelinhalt angezeigt wird und sichtbar wird, wenn der Inhalt wischt.
Einfaches Beispiel: Aktualisieren oder schließen durch Wischen
Die Snippets in diesem Beispiel zeigen eine Wischimplementierung, bei der das Element entweder aktualisiert wird, wenn von Anfang nach Ende gewischt wird, oder geschlossen wird, wenn von Ende nach 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
swipeToDismissBoxState
verwaltet den Komponentenstatus. Er löst denconfirmValueChange
-Callback aus, sobald die Interaktion mit dem Artikel abgeschlossen ist. Im Callback-Body werden die verschiedenen möglichen Aktionen verarbeitet. 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 wischt, wird das
onToggleDone
-Lambda aufgerufen und die aktuelletodoItem
übergeben. Das entspricht dem Aktualisieren des To-do-Eintrags. - Wenn das Element vom Ende zum Anfang wischt, wird das Lambda-Objekt
onRemove
aufgerufen und die aktuelletodoItem
übergeben. Das entspricht dem Löschen des To-do-Eintrags. it != StartToEnd
: Diese Zeile gibttrue
zurück, wenn die Wischrichtung nichtStartToEnd
ist, andernfallsfalse
. Wenn Siefalse
zurückgeben, verschwindetSwipeToDismissBox
nicht sofort nach dem Wischen zum Ausschalten. So ist eine visuelle Bestätigung oder Animation möglich.
- Wenn das Element von Anfang bis Ende wischt, wird das
- Mit
SwipeToDismissBox
können Sie bei jedem Element horizontal wischen. Im Ruhemodus wird der innere Inhalt der Komponente angezeigt. Wenn ein Nutzer jedoch wischt, wird der Inhalt ausgeblendet und dasbackgroundContent
wird angezeigt. Sowohl die normalen Inhalte als auch dasbackgroundContent
erhalten die vollständigen Einschränkungen des übergeordneten Containers, in dem sie gerendert werden. Dascontent
wird über dembackgroundContent
gezeichnet. In diesem Fall:backgroundContent
wird alsIcon
mit einer Hintergrundfarbe implementiert, die aufSwipeToDismissBoxValue
basiert:Blue
beim Wischen aufStartToEnd
: Ein-/Ausschalten eines To-do-Eintrags.Red
beim Wischen aufEndToStart
: Löschen eines To-do-Eintrags.- Für
Settled
wird im Hintergrund nichts angezeigt. Wenn das Element nicht gewischt wird, wird im Hintergrund nichts angezeigt. - Ebenso passt sich das angezeigte
Icon
an die Wischrichtung an: - Bei
StartToEnd
wird das SymbolCheckBox
angezeigt, wenn die Aufgabe erledigt ist, und das SymbolCheckBoxOutlineBlank
, wenn sie noch nicht erledigt ist. EndToStart
wird einDelete
-Symbol angezeigt.
@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 Observable-Liste, dieTodoItem
-Objekte enthalten kann. Wenn ein Element dieser Liste hinzugefügt oder daraus entfernt wird, werden die entsprechenden Teile der Benutzeroberfläche in Compose neu zusammengesetzt.- Innerhalb von
mutableStateListOf()
werden vierTodoItem
-Objekte mit ihren jeweiligen Beschreibungen initialisiert: „Rechnungen bezahlen“, „Einkäufe erledigen“, „In die Turnhalle gehen“ und „Abendessen holen“.
- Innerhalb von
- Mit
LazyColumn
wird eine vertikal scrollbare Liste vontodoItems
angezeigt. onToggleDone = { todoItem -> ... }
ist eine Callback-Funktion, die vonTodoListItem
aufgerufen wird, wenn der Nutzer ein Objekt als erledigt markiert. Dadurch wird das AttributisItemDone
destodoItem
aktualisiert. DatodoItems
einmutableStateListOf
ist, 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 das Element entfernt. Dadurch wird die spezifischetodoItem
aus der Liste dertodoItems
entfernt. Dadurch wird auch die Zusammensetzung neu berechnet und das Element wird aus der angezeigten Liste entfernt.- Auf jede
TodoListItem
wird einanimateItem
-Modifikator angewendet, damit dieplacementSpec
des Modifikators aufgerufen wird, wenn das Element geschlossen wurde. Dadurch wird das Entfernen des Artikels sowie die Neuanordnung anderer Artikel in der Liste animiert.
Ergebnis
Im folgenden Video wird die grundlegende Funktion „Wischen zum Schließen“ aus den vorherigen Snippets veranschaulicht:
Den vollständigen Code finden Sie in der GitHub-Quelldatei.
Fortgeschrittenes Beispiel: Hintergrundfarbe beim Wischen animieren
In den folgenden Snippets wird gezeigt, wie Sie einen Positionsgrenzwert verwenden, 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
drawBehind
wird direkt in den Canvas hinter dem Inhalt desIcon
-Kompositionselements gezeichnet.drawRect()
zeichnet ein Rechteck auf dem Canvas und füllt den gesamten Zeichnungsbereich mit dem angegebenenColor
aus.
- Beim Wischen ändert sich die Hintergrundfarbe des Artikels mit
lerp
stufenlos.- Bei einem Wischen von
StartToEnd
ändert sich die Hintergrundfarbe nach und nach von Hellgrau zu Blau. - Bei einem Wischen von
EndToStart
ändert sich die Hintergrundfarbe nach und nach von Hellgrau zu Rot. - Der Übergang von einer Farbe zur nächsten wird durch
swipeToDismissBoxState.progress
bestimmt.
- Bei einem Wischen von
OutlinedCard
sorgt für eine subtile visuelle Trennung zwischen den Listenelementen.
@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
- Die wichtigsten Punkte zu diesem Code finden Sie unter Wichtige Punkte in einem vorherigen Abschnitt, in dem ein identisches Code-Snippet beschrieben wird.
Ergebnis
Im folgenden Video sind die erweiterten Funktionen mit animierter Hintergrundfarbe zu sehen:
Den vollständigen Code finden Sie in der GitHub-Quelldatei.