O componente SwipeToDismissBox permite que o usuário dispense ou atualize um
item deslizando-o para a esquerda ou direita.
Superfície da API
Use o elemento combinável SwipeToDismissBox para implementar ações acionadas
por gestos de deslizar. Os principais parâmetros incluem:
state: o estadoSwipeToDismissBoxStatecriado para armazenar o valor produzido por cálculos no item de deslizar, que aciona eventos quando produzido.backgroundContent: um elemento combinável personalizável exibido atrás do conteúdo do item, que é revelado quando o conteúdo é deslizado.
Exemplo básico: atualizar ou dispensar ao deslizar
Os snippets neste exemplo mostram uma implementação de deslize que atualiza o item quando deslizado do início para o fim ou dispensa o item quando deslizado do fim para o início.
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.") } ) } }
Pontos principais sobre o código
swipeToDismissBoxStategerencia o estado do componente. Ele aciona o callbackconfirmValueChangequando a interação com o item é concluída. O corpo do callback processa as diferentes ações possíveis. O callback retorna um booleano que informa ao componente se ele precisa mostrar uma animação de encerramento. Nesse caso:- Se o item for deslizado do início ao fim, ele vai chamar o lambda 
onToggleDone, transmitindo otodoItematual. Isso corresponde à atualização do item de tarefas. - Se o item for deslizado do fim para o início, ele vai chamar o lambda 
onRemove, transmitindo otodoItematual. Isso corresponde à exclusão do item de tarefas. it != StartToEnd: essa linha retornatruese a direção do deslizar não forStartToEndefalsecaso contrário. O retorno defalseimpede que oSwipeToDismissBoxdesapareça imediatamente após um deslize de "alternar concluído", permitindo uma confirmação visual ou animação.
- Se o item for deslizado do início ao fim, ele vai chamar o lambda 
 SwipeToDismissBoxativa interações de deslizar horizontal em cada item. Em repouso, ele mostra o conteúdo interno do componente, mas quando um usuário começa a deslizar, o conteúdo é removido e obackgroundContentaparece. Tanto o conteúdo normal quanto obackgroundContentrecebem as restrições completas do contêiner pai para renderização. Ocontenté desenhado sobre obackgroundContent. Nesse caso:backgroundContenté implementado como umaIconcom uma cor de plano de fundo baseada emSwipeToDismissBoxValue:Blueao deslizarStartToEnd: alternar um item de tarefas.Redao deslizarEndToStart: excluir uma tarefa.- Nada é exibido no segundo plano para 
Settled. Quando o item não está sendo deslizado, nada é mostrado no segundo plano. - Da mesma forma, o 
Iconexibido se adapta à direção do movimento: StartToEndmostra um íconeCheckBoxquando a tarefa é concluída e um íconeCheckBoxOutlineBlankquando ela não é concluída.EndToStartexibe um íconeDelete.
@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() ) } } }
Pontos principais sobre o código
mutableStateListOf(...)cria uma lista observável que pode conter objetosTodoItem. Quando um item é adicionado ou removido dessa lista, o Compose recompone as partes da IU que dependem dele.- Dentro de 
mutableStateListOf(), quatro objetosTodoItemsão inicializados com as respectivas descrições: "Pay bills", "Buy groceries", "Go to gym" e "Get dinner". 
- Dentro de 
 LazyColumnmostra uma lista detodoItemscom rolagem vertical.onToggleDone = { todoItem -> ... }é uma função de callback invocada emTodoListItemquando o usuário marca um objeto como concluído. Ele atualiza a propriedadeisItemDonedotodoItem. ComotodoItemsé ummutableStateListOf, essa mudança aciona uma recomposição, atualizando a interface.onRemove = { todoItem -> ... }é uma função de callback acionada quando o usuário remove o item. Ele remove otodoItemespecífico da listatodoItems. Isso também causa uma recomposição, e o item será removido da lista exibida.- Um modificador 
animateItemé aplicado a cadaTodoListItempara que oplacementSpecdo modificador seja chamado quando o item for dispensado. Isso anima a remoção do item, bem como a reordenação de outros itens na lista. 
Resultado
O vídeo a seguir demonstra a funcionalidade básica de deslizar para descartar dos snipets anteriores:
Consulte o arquivo de origem do GitHub para conferir o código de exemplo completo.
Exemplo avançado: animar a cor do plano de fundo ao deslizar
Os snippets a seguir mostram como incorporar um limite posicional para animar a cor de fundo de um item ao deslizar.
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.") } ) } } }
Pontos principais sobre o código
- O 
drawBehindé exibido diretamente na tela por trás do conteúdo do elemento combinávelIcon.drawRect()desenha um retângulo na tela e preenche todos os limites do escopo de exibição com oColorespecificado.
 - Ao deslizar, a cor de plano de fundo do item muda suavemente usando
lerp.- Em um deslize de 
StartToEnd, a cor de fundo muda gradualmente de cinza claro para azul. - Para um deslize de 
EndToStart, a cor de fundo muda gradualmente de cinza claro para vermelho. - A quantidade de transição de uma cor para a próxima é determinada por
swipeToDismissBoxState.progress. 
 - Em um deslize de 
 - O 
OutlinedCardadiciona uma separação visual sutil entre os itens da lista. 
@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() ) } } }
Pontos principais sobre o código
- Para conferir os principais pontos sobre esse código, consulte Principais pontos em uma seção anterior, que descreve um snippet de código idêntico.
 
Resultado
O vídeo a seguir mostra a funcionalidade avançada com a cor de plano de fundo animada:
Consulte o arquivo de origem do GitHub para conferir o código de exemplo completo.