Il componente SwipeToDismissBox consente a un utente di ignorare o aggiornare un elemento scorrendo verso sinistra o verso destra.
API surface
Utilizza il composable SwipeToDismissBox per implementare le azioni attivate
da gesti di scorrimento. I parametri principali includono:
state: lo statoSwipeToDismissBoxStatecreato per memorizzare il valore prodotto dai calcoli sull'elemento scorrimento, che attiva gli eventi quando viene prodotto.backgroundContent: un componibile personalizzabile visualizzato dietro i contenuti dell'articolo che viene rivelato quando si scorre.
Esempio di base: aggiornamento o chiusura con scorrimento
Gli snippet in questo esempio mostrano un'implementazione dello scorrimento che aggiorna l'elemento quando viene eseguito dall'inizio alla fine o lo chiude quando viene eseguito dalla fine all'inizio.
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.") } ) } }
Punti chiave del codice
swipeToDismissBoxStategestisce lo stato del componente. Attiva il callbackconfirmValueChangeal termine dell'interazione con l'elemento. Il corpo del callback gestisce le diverse azioni possibili. Il callback restituisce un valore booleano che indica al componente se deve mostrare un'animazione di chiusura. In questo caso:- Se l'elemento viene strisciato dall'inizio alla fine, viene chiamata la funzione lambda 
onToggleDone, passando l'attualetodoItem. Questo corrisponde all'aggiornamento dell'elemento della lista di cose da fare. - Se l'elemento viene strisciato dall'inizio alla fine, viene chiamata la funzione lambda 
onRemove, passando l'attualetodoItem. Ciò corrisponde all'eliminazione dell'elemento della lista di cose da fare. it != StartToEnd: questa riga restituiscetruese la direzione dello scorrimento non èStartToEndefalsein caso contrario. Il ritorno afalseimpedisce cheSwipeToDismissBoxscompaia immediatamente dopo uno scorrimento "Attiva/Disattiva completato", consentendo una conferma visiva o un'animazione.
- Se l'elemento viene strisciato dall'inizio alla fine, viene chiamata la funzione lambda 
 SwipeToDismissBoxconsente le interazioni con scorrimento orizzontale su ogni elemento. In stato di riposo, mostra i contenuti interni del componente, ma quando un utente inizia a scorrere, i contenuti vengono spostati e viene visualizzatobackgroundContent. Sia i contenuti normali siabackgroundContentricevono i vincoli completi del contenitore principale per il rendering. Ilcontentviene disegnato sopra ilbackgroundContent. In questo caso:backgroundContentè implementato comeIconcon un colore di sfondo basato suSwipeToDismissBoxValue:Bluequando scorriStartToEnd: attiva/disattiva un elemento della lista di cose da fare.Redquando scorriEndToStart: eliminazione di un elemento della lista di cose da fare.- Non viene visualizzato nulla in background per 
Settled: quando l'elemento non viene scorretto, non viene visualizzato nulla in background. - Allo stesso modo, il 
Iconvisualizzato si adatta alla direzione dello scorrimento: StartToEndmostra un'iconaCheckBoxquando l'elemento della lista di cose da fare è stato completato e un'iconaCheckBoxOutlineBlankquando non è stato completato.EndToStartviene visualizzata un'iconaDelete.
@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() ) } } }
Punti chiave del codice
mutableStateListOf(...)crea un elenco osservabile che può contenere oggettiTodoItem. Quando un elemento viene aggiunto o rimosso da questo elenco, Compose ricomponie le parti dell'interfaccia utente che dipendono da esso.- All'interno di 
mutableStateListOf(), vengono inizializzati quattro oggettiTodoItemcon le rispettive descrizioni: "Paga le bollette", "Fai la spesa", "Vai in palestra" e "Prendi la cena". 
- All'interno di 
 LazyColumnmostra un elenco ditodoItemsin scorrimento verticale.onToggleDone = { todoItem -> ... }è una funzione di callback invocata daTodoListItemquando l'utente contrassegna un oggetto come completato. Aggiorna la proprietàisItemDoneditodoItem. PoichétodoItemsè unmutableStateListOf, questa modifica attiva una ricompozione, aggiornando l'interfaccia utente.onRemove = { todoItem -> ... }è una funzione di callback attivata quando l'utente rimuove l'elemento. Rimuove iltodoItemspecifico dall'elencotodoItems. Ciò comporta anche una ricostituzione e l'elemento verrà rimosso dall'elenco visualizzato.- A ogni 
TodoListItemviene applicato un modificatoreanimateItemin modo che ilplacementSpecdel modificatore venga chiamato quando l'elemento viene ignorato. In questo modo viene animata la rimozione dell'elemento, nonché il riordinamento degli altri elementi nell'elenco. 
Risultato
Il video seguente mostra la funzionalità di scorrimento per chiudere di base degli snippet precedenti:
Per il codice di esempio completo, consulta il file di origine di GitHub.
Esempio avanzato: animare il colore di sfondo con lo scorrimento
Gli snippet riportati di seguito mostrano come incorporare una soglia di posizione per animare il colore di sfondo di un elemento quando viene scorretto.
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.") } ) } } }
Punti chiave del codice
drawBehindviene disegnato direttamente nella tela dietro i contenuti del composableIcon.drawRect()disegna un rettangolo sul canvas e riempie l'intero ambito del disegno con il coloreColorspecificato.
- Quando scorri, il colore di sfondo dell'elemento passa gradualmente da un colore all'altro utilizzando
lerp.- Se scorri da 
StartToEnd, il colore di sfondo cambia gradualmente da grigio chiaro a blu. - Se scorri da 
EndToStart, il colore di sfondo cambia gradualmente da grigio chiaro a rosso. - L'entità della transizione da un colore all'altro è determinata da
swipeToDismissBoxState.progress. 
 - Se scorri da 
 OutlinedCardaggiunge una sottile separazione visiva tra le voci dell'elenco.
@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() ) } } }
Punti chiave del codice
- Per i punti chiave di questo codice, consulta Punti chiave di una sezione precedente, che descrive uno snippet di codice identico.
 
Risultato
Il video seguente mostra la funzionalità avanzata con colore di sfondo animato:
Per il codice di esempio completo, consulta il file di origine di GitHub.