Thành phần SwipeToDismissBox cho phép người dùng đóng hoặc cập nhật một mục bằng cách vuốt mục đó sang trái hoặc phải.
Nền tảng API
Sử dụng thành phần kết hợp SwipeToDismissBox để triển khai các thao tác được kích hoạt bằng cử chỉ vuốt. Các tham số chính bao gồm:
state: Trạng tháiSwipeToDismissBoxStateđược tạo để lưu trữ giá trị do các phép tính trên mục vuốt tạo ra, từ đó kích hoạt các sự kiện khi được tạo.backgroundContent: Một thành phần kết hợp có thể tuỳ chỉnh hiển thị phía sau nội dung mục được hiển thị khi nội dung được vuốt.
Ví dụ cơ bản: Cập nhật hoặc đóng khi vuốt
Các đoạn mã trong ví dụ này cho thấy cách triển khai thao tác vuốt để cập nhật mục khi vuốt từ đầu đến cuối hoặc đóng mục khi vuốt từ cuối đến đầu.
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.") } ) } }
Các điểm chính về mã
swipeToDismissBoxStatequản lý trạng thái thành phần. Phương thức này sẽ kích hoạt lệnh gọi lạiconfirmValueChangesau khi tương tác với mục đó. Phần nội dung lệnh gọi lại xử lý các thao tác có thể thực hiện. Lệnh gọi lại trả về một boolean cho thành phần biết liệu thành phần đó có hiển thị ảnh động đóng hay không. Trong trường hợp này:- Nếu bạn vuốt mục từ đầu đến cuối, thì thao tác này sẽ gọi lambda 
onToggleDone, truyềntodoItemhiện tại. Thao tác này tương ứng với việc cập nhật mục cần làm. - Nếu bạn vuốt mục từ cuối đến đầu, thì thao tác này sẽ gọi hàm lambda 
onRemove, truyềntodoItemhiện tại. Điều này tương ứng với việc xoá mục cần làm. it != StartToEnd: Dòng này trả vềtruenếu hướng vuốt không phải làStartToEndvàfalsenếu không. Việc trả vềfalsesẽ ngănSwipeToDismissBoxbiến mất ngay sau khi vuốt "đã bật/tắt", cho phép xác nhận bằng hình ảnh hoặc ảnh động.
- Nếu bạn vuốt mục từ đầu đến cuối, thì thao tác này sẽ gọi lambda 
 SwipeToDismissBoxcho phép tương tác vuốt theo chiều ngang trên từng mục. Ở trạng thái nghỉ, thành phần này hiển thị nội dung bên trong của thành phần, nhưng khi người dùng bắt đầu vuốt, nội dung sẽ được di chuyển ra xa vàbackgroundContentsẽ xuất hiện. Cả nội dung thông thường vàbackgroundContentđều nhận được các quy tắc ràng buộc đầy đủ của vùng chứa mẹ để hiển thị chính nội dung đó.contentđược vẽ trênbackgroundContent. Trong trường hợp này:backgroundContentđược triển khai dưới dạngIconcó màu nền dựa trênSwipeToDismissBoxValue:Bluekhi vuốtStartToEnd– bật/tắt một việc cần làm.Redkhi vuốtEndToStart– xoá một việc cần làm.- Không có gì hiển thị ở chế độ nền cho 
Settled– khi mục không được vuốt, không có gì hiển thị ở chế độ nền. - Tương tự, 
Iconhiển thị sẽ điều chỉnh theo hướng vuốt: StartToEndhiển thị biểu tượngCheckBoxkhi việc cần làm đã hoàn tất và biểu tượngCheckBoxOutlineBlankkhi việc cần làm chưa hoàn tất.EndToStarthiển thị biểu tượngDelete.
@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() ) } } }
Các điểm chính về mã
mutableStateListOf(...)tạo một danh sách có thể quan sát có thể chứa các đối tượngTodoItem. Khi một mục được thêm hoặc xoá khỏi danh sách này, Compose sẽ kết hợp lại các phần của giao diện người dùng phụ thuộc vào mục đó.- Bên trong 
mutableStateListOf(), 4 đối tượngTodoItemđược khởi tạo với nội dung mô tả tương ứng: "Thanh toán hoá đơn", "Mua đồ ăn", "Đi tập thể dục" và "Ăn tối". 
- Bên trong 
 LazyColumnhiển thị danh sáchtodoItemscuộn theo chiều dọc.onToggleDone = { todoItem -> ... }là một hàm gọi lại được gọi từ trongTodoListItemkhi người dùng đánh dấu một đối tượng là đã hoàn tất. Phương thức này cập nhật thuộc tínhisItemDonecủatodoItem. VìtodoItemslà mộtmutableStateListOf, nên thay đổi này sẽ kích hoạt quá trình kết hợp lại, cập nhật giao diện người dùng.onRemove = { todoItem -> ... }là một hàm gọi lại được kích hoạt khi người dùng xoá mục. Thao tác này sẽ xoátodoItemcụ thể khỏi danh sáchtodoItems. Điều này cũng gây ra quá trình kết hợp lại và mục sẽ bị xoá khỏi danh sách hiển thị.- Đối tượng sửa đổi 
animateItemđược áp dụng cho mỗiTodoListItemđểplacementSpeccủa đối tượng sửa đổi được gọi khi mục đã bị loại bỏ. Thao tác này sẽ tạo ảnh động cho việc xoá mục, cũng như sắp xếp lại các mục khác trong danh sách. 
Kết quả
Video sau đây minh hoạ chức năng vuốt để đóng cơ bản từ các đoạn mã trước:
Hãy xem tệp nguồn GitHub để biết toàn bộ mã mẫu.
Ví dụ nâng cao: Tạo ảnh động cho màu nền khi vuốt
Các đoạn mã sau đây cho biết cách kết hợp ngưỡng vị trí để tạo ảnh động cho màu nền của một mục khi vuốt.
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.") } ) } } }
Các điểm chính về mã
drawBehindvẽ trực tiếp vào canvas phía sau nội dung của thành phần kết hợpIcon.drawRect()vẽ một hình chữ nhật trên canvas và lấp đầy toàn bộ ranh giới của phạm vi vẽ bằngColorđã chỉ định.
- Khi vuốt, màu nền của mục sẽ chuyển đổi suôn sẻ bằng cách sử dụng 
lerp.- Khi vuốt từ 
StartToEnd, màu nền sẽ thay đổi dần từ màu xám nhạt sang màu xanh dương. - Khi vuốt từ 
EndToStart, màu nền sẽ thay đổi dần từ màu xám nhạt sang màu đỏ. - Mức độ chuyển đổi từ màu này sang màu khác được xác định bằng 
swipeToDismissBoxState.progress. 
 - Khi vuốt từ 
 OutlinedCardtạo ra một sự phân tách hình ảnh tinh tế giữa các mục trong danh sách.
@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() ) } } }
Các điểm chính về mã
- Để biết các điểm chính về mã này, hãy xem phần Các điểm chính trong phần trước. Phần này mô tả một đoạn mã giống hệt.
 
Kết quả
Video sau đây cho thấy chức năng nâng cao với màu nền động:
Hãy xem tệp nguồn GitHub để biết toàn bộ mã mẫu.