Komponen SwipeToDismissBox
memungkinkan pengguna menutup atau memperbarui
item dengan menggesernya ke kiri atau kanan.
Platform API
Gunakan composable SwipeToDismissBox
untuk menerapkan tindakan yang dipicu
oleh gestur geser. Parameter utamanya meliputi:
state
: StatusSwipeToDismissBoxState
yang dibuat untuk menyimpan nilai yang dihasilkan oleh penghitungan pada item geser, yang memicu peristiwa saat dibuat.backgroundContent
: Composable yang dapat disesuaikan yang ditampilkan di belakang konten item yang ditampilkan saat konten digeser.
Contoh dasar: Memperbarui atau menutup dengan menggeser
Cuplikan dalam contoh ini menunjukkan implementasi geser yang memperbarui item saat digeser dari awal hingga akhir, atau menutup item saat digeser dari akhir ke awal.
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.") } ) } }
Poin-poin penting tentang kode
swipeToDismissBoxState
mengelola status komponen. Tindakan ini memicu callbackconfirmValueChange
setelah interaksi dengan item selesai. Isi callback menangani berbagai kemungkinan tindakan. Callback menampilkan boolean yang memberi tahu komponen apakah harus menampilkan animasi penonaktifan. Dalam hal ini:- Jika item digeser dari awal hingga akhir, item tersebut akan memanggil lambda
onToggleDone
, yang meneruskantodoItem
saat ini. Hal ini sesuai dengan memperbarui item daftar tugas. - Jika item digeser dari akhir ke awal, item tersebut akan memanggil lambda
onRemove
, yang meneruskantodoItem
saat ini. Tindakan ini sesuai dengan penghapusan item daftar tugas. it != StartToEnd
: Baris ini menampilkantrue
jika arah geser bukanStartToEnd
, danfalse
jika sebaliknya. Menampilkanfalse
mencegahSwipeToDismissBox
langsung menghilang setelah geser "tombol selesai", sehingga memungkinkan konfirmasi atau animasi visual.
- Jika item digeser dari awal hingga akhir, item tersebut akan memanggil lambda
SwipeToDismissBox
memungkinkan interaksi geser horizontal pada setiap item. Dalam istirahat, komponen ini menampilkan konten bagian dalam komponen, tetapi saat pengguna mulai menggeser, konten akan dipindahkan danbackgroundContent
akan muncul. Konten normal danbackgroundContent
mendapatkan batasan penuh penampung induk untuk merendernya.content
digambar di atasbackgroundContent
. Dalam hal ini:backgroundContent
diterapkan sebagaiIcon
dengan warna latar belakang berdasarkanSwipeToDismissBoxValue
:Blue
saat menggeserStartToEnd
— mengalihkan item daftar tugas.Red
saat menggeserEndToStart
— menghapus item daftar tugas.- Tidak ada yang ditampilkan di latar belakang untuk
Settled
— saat item tidak digeser, tidak ada yang ditampilkan di latar belakang. - Demikian pula,
Icon
yang ditampilkan akan menyesuaikan dengan arah geser: StartToEnd
menampilkan ikonCheckBox
saat item daftar tugas selesai dan ikonCheckBoxOutlineBlank
saat belum selesai.EndToStart
menampilkan ikonDelete
.
@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() ) } } }
Poin-poin penting tentang kode
mutableStateListOf(...)
membuat daftar yang dapat diamati yang dapat menyimpan objekTodoItem
. Saat item ditambahkan atau dihapus dari daftar ini, Compose akan merekomposisi bagian UI yang bergantung padanya.- Di dalam
mutableStateListOf()
, empat objekTodoItem
diinisialisasi dengan deskripsi masing-masing: "Bayar tagihan", "Beli bahan makanan", "Pergi ke gym", dan "Beli makan malam".
- Di dalam
LazyColumn
menampilkan daftartodoItems
yang di-scroll secara vertikal.onToggleDone = { todoItem -> ... }
adalah fungsi callback yang dipanggil dari dalamTodoListItem
saat pengguna menandai objek sebagai selesai. Class ini memperbarui propertiisItemDone
daritodoItem
. KarenatodoItems
adalahmutableStateListOf
, perubahan ini memicu rekomposisi, yang mengupdate UI.onRemove = { todoItem -> ... }
adalah fungsi callback yang dipicu saat pengguna menghapus item. Tindakan ini akan menghapustodoItem
tertentu dari daftartodoItems
. Tindakan ini juga menyebabkan rekomposisi, dan item akan dihapus dari daftar yang ditampilkan.- Pengubah
animateItem
diterapkan ke setiapTodoListItem
sehinggaplacementSpec
pengubah dipanggil saat item ditutup. Tindakan ini akan menganimasikan penghapusan item, serta pengurutan ulang item lain dalam daftar.
Hasil
Video berikut menunjukkan fungsi geser untuk menutup dasar dari cuplikan sebelumnya:
Lihat file sumber GitHub untuk mengetahui kode contoh lengkap.
Contoh lanjutan: Menganimasikan warna latar belakang saat menggeser
Cuplikan berikut menunjukkan cara menggabungkan nilai minimum posisi untuk menganimasikan warna latar belakang item saat menggeser.
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.") } ) } } }
Poin-poin penting tentang kode
drawBehind
menggambar langsung ke kanvas di belakang konten composableIcon
.drawRect()
menggambar persegi panjang di kanvas dan mengisi seluruh batas cakupan gambar denganColor
yang ditentukan.
- Saat menggeser, warna latar belakang item akan bertransisi dengan lancar menggunakan
lerp
.- Untuk geser dari
StartToEnd
, warna latar belakang secara bertahap berubah dari abu-abu terang menjadi biru. - Untuk geser dari
EndToStart
, warna latar belakang secara bertahap berubah dari abu-abu terang menjadi merah. - Jumlah transisi dari satu warna ke warna berikutnya ditentukan oleh
swipeToDismissBoxState.progress
.
- Untuk geser dari
OutlinedCard
menambahkan pemisahan visual yang halus di antara item daftar.
@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() ) } } }
Poin-poin penting tentang kode
- Untuk mengetahui poin-poin penting tentang kode ini, lihat Poin-poin penting dari bagian sebelumnya, yang menjelaskan cuplikan kode yang identik.
Hasil
Video berikut menunjukkan fungsi lanjutan dengan warna latar belakang animasikan:
Lihat file sumber GitHub untuk mengetahui kode contoh lengkap.