Komponent SwipeToDismissBox pozwala użytkownikowi odrzucić lub zaktualizować element, przesuwając go w lewo lub w prawo.
Interfejs API
Aby zaimplementować działania wywoływane przez gesty przesuwania, użyj komponentu SwipeToDismissBox. Kluczowe parametry:
state: stanSwipeToDismissBoxStateutworzony w celu przechowywania wartości wygenerowanej przez obliczenia dotyczące elementu przesuwania, który uruchamia zdarzenia po wygenerowaniu.backgroundContent: konfigurowalny element kompozycyjny wyświetlany za treścią, który ujawnia się po przesunięciu treści.
Przykład podstawowy: aktualizacja lub zamknięcie po przesunięciu
W tym przykładzie fragmenty kodu pokazują implementację przesuwania, która aktualizuje element, gdy przesuniesz go od początku do końca, lub zamyka go, gdy przesuniesz go od końca do początku.
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.") } ) } }
Najważniejsze informacje o kodzie
swipeToDismissBoxStatezarządza stanem komponentu. Po zakończeniu interakcji z elementem wywołuje on funkcjęconfirmValueChange. Treść wywołania zwrotnego obsługuje różne możliwe działania. Wywołanie zwrotne zwraca wartość logiczną, która informuje komponent, czy ma wyświetlić animację zamykania. W tym przypadku:- Jeśli element jest przesuwany od początku do końca, wywołuje funkcję 
onToggleDonelambda, przekazując bieżącą wartośćtodoItem. Odpowiada to aktualizowaniu elementu listy zadań. - Jeśli element jest przesuwany od końca do początku, wywołuje funkcję 
onRemovelambda, przekazując bieżącą wartośćtodoItem. Odpowiada to usunięciu zadania. it != StartToEnd: ta linijka zwraca wartośćtrue, jeśli kierunek przesunięcia nie jestStartToEnd, a w przeciwnym razie zwraca wartośćfalse. Zwracaniefalsezapobiega natychmiastowemu zniknięciuSwipeToDismissBoxpo przesunięciu palcem, co umożliwia wizualne potwierdzenie lub animację.
- Jeśli element jest przesuwany od początku do końca, wywołuje funkcję 
 SwipeToDismissBoxumożliwia przesuwanie elementów poziomo. W przypadku Pinteresta pokazuje ona wewnętrzną zawartość komponentu, ale gdy użytkownik zacznie przesuwać palcem, treść zostanie usunięta i pojawi siębackgroundContent. Zarówno normalna zawartość, jak ibackgroundContentmają pełne ograniczenia kontenera nadrzędnego, w którym są renderowane.contentjest narysowana na wierzchubackgroundContent. W tym przypadku:backgroundContentjest implementowany jakoIconz kolorem tła opartym naSwipeToDismissBoxValue:Bluepodczas przesuwaniaStartToEnd– włączanie i wyłączanie elementu listy zadań.Redpodczas przesuwaniaEndToStart– usuwanie zadania.- W przypadku 
Settledtło nie jest wyświetlane – gdy element nie jest przesuwany, tło nie jest wyświetlane. - Podobnie wyświetlana 
Icondostosowuje się do kierunku przesuwania: StartToEndwyświetla ikonęCheckBox, gdy zadanie jest wykonane, i ikonęCheckBoxOutlineBlank, gdy nie jest wykonane.EndToStartwyświetla ikonęDelete.
@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() ) } } }
Najważniejsze informacje o kodzie
mutableStateListOf(...)tworzy obserwowalną listę, która może zawierać obiektyTodoItem. Gdy element zostanie dodany do tej listy lub z niej usunięty, Compose ponownie utworzy te części interfejsu, które na nim polegają.- Wewnątrz 
mutableStateListOf()inicjowane są 4 obiektyTodoItemz odpowiednimi opisami: „Opłacanie rachunków”, „Zakupy spożywcze”, „Chodzenie na siłownię” i „Kolacja”. 
- Wewnątrz 
 LazyColumnwyświetla listętodoItemsprzewijaną w pionie.onToggleDone = { todoItem -> ... }to funkcja wywołania zwrotnego wywoływana z poziomuTodoListItem, gdy użytkownik zaznaczy obiekt jako gotowy. Zmień właściwośćisItemDonew komponencietodoItem. PonieważtodoItemsjestmutableStateListOf, ta zmiana powoduje ponowne skompilowanie i zaktualizowanie interfejsu.onRemove = { todoItem -> ... }to funkcja wywołania zwrotnego, która jest wywoływana, gdy użytkownik usunie element. Usuwa określony elementtodoItemz listytodoItems. Spowoduje to również ponowne złożenie listy, a element zostanie usunięty z wyświetlanej listy.- Modyfikator 
animateItemjest stosowany do każdego elementuTodoListItem, aby wywołać funkcjęplacementSpecmodyfikatora po odrzuceniu elementu. W tym celu animujesz usunięcie elementu oraz zmianę kolejności innych elementów na liście. 
Wynik
Ten film pokazuje podstawową funkcję przesuwania, aby zamknąć, z poprzednich fragmentów kodu:
Pełny przykładowy kod znajdziesz w pliku źródłowym na GitHubie.
Przykład zaawansowany: animacja koloru tła podczas przesuwania
Poniższe fragmenty kodu pokazują, jak zastosować próg pozycji, aby animować kolor tła elementu podczas przesuwania.
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.") } ) } } }
Najważniejsze informacje o kodzie
drawBehindrysuje bezpośrednio na płótnie za treścią elementuIcon.drawRect()rysuje prostokąt na płótnie i wypełnia cały zakres rysunku określonymColor.
- Podczas przesuwania kolor tła elementu zmienia się płynnie za pomocą funkcji 
lerp.- W przypadku przesunięcia z poziomu 
StartToEndkolor tła stopniowo zmienia się z jasnego szarego na niebieski. - W przypadku przesunięcia z 
EndToStartkolor tła stopniowo zmienia się z jasnego szarego na czerwony. - Wielkość przejścia z jednego koloru na następny określa parametr 
swipeToDismissBoxState.progress. 
 - W przypadku przesunięcia z poziomu 
 OutlinedCarddodaje subtelne wizualne oddzielenie między elementami listy.
@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() ) } } }
Najważniejsze informacje o kodzie
- Najważniejsze informacje o tym kodzie znajdziesz w sekcji Najważniejsze informacje w poprzedniej sekcji, która zawiera identyczny fragment kodu.
 
Wynik
Ten film pokazuje zaawansowane funkcje z animowanym tłem:
Pełny przykładowy kod znajdziesz w pliku źródłowym na GitHubie.