عنصر SwipeToDismissBox به کاربر امکان میدهد با تند کشیدن مورد به چپ یا راست، آن را ببندد یا بهروز کند.
سطح میانای برنامهسازی کاربردی
از عنصر ترکیبی SwipeToDismissBox برای پیادهسازی کنشهایی که با اشارههای تند کشیدن راهاندازی میشوند استفاده کنید. پارامترهای کلیدی شامل موارد زیر است:
state: وضعیتSwipeToDismissBoxStateایجادشده برای ذخیره مقدار تولیدشده توسط محاسبات روی عنصر تند کشیدن، که رویدادها را هنگام تولید شدن راهاندازی میکند.backgroundContent: عنصر ترکیبی سفارشیسازیشدنی که در پشت محتوای مورد نمایش داده میشود و وقتی محتوا تند کشیده میشود آشکار میشود.
مثال پایه: بهروزرسانی یا بستن با تند کشیدن
گزیدههای این مثال پیادهسازی کشیدنی را نشان میدهد که یا وقتی از ابتدا به انتها کشیده میشود مورد را بهروز میکند، یا وقتی از انتها به ابتدا کشیده میشود مورد را میبندد.
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.") } ) } }
نکات کلیدی درباره کد
-
swipeToDismissBoxStateوضعیت عنصر را مدیریت میکند. وقتی تعامل با مورد تمام شد،confirmValueChangeپاسخگویی را راهاندازی میکند. بدنه بازخوانی کنشهای ممکن مختلف را مدیریت میکند. این برگشتتماس یک مقدار بولی برمیگرداند که به عنصر میگوید آیا باید پویانمایی بستن را نمایش دهد یا نه. در این مورد:- اگر محصول از ابتدا تا انتها تند کشیده شود،
onToggleDoneلامبدا را فرا میخواند وtodoItemکنونی را ارسال میکند. این با بهروزرسانی مورد کار مطابقت دارد. - اگر محصول از انتها به ابتدا تند کشیده شود، تابع لامبدای
onRemoveرا فرا میخواند وtodoItemفعلی را ارسال میکند. این کار با حذف کردن مورد کارها مطابقت دارد. -
it != StartToEnd: اگر جهت تند کشیدنStartToEndنباشد، این خطtrueرا برمیگرداند، و درغیراینصورتfalseرا برمیگرداند. برگرداندنfalseباعث میشودSwipeToDismissBoxبلافاصله پساز کشیدن «تغییر وضعیت انجام شد» ناپدید نشود و امکان تأیید دیداری یا پویانمایی را فراهم میکند.
- اگر محصول از ابتدا تا انتها تند کشیده شود،
SwipeToDismissBoxتعاملات تند کشیدن افقی را در هر مورد فعال میکند. در حالت استراحت، محتوای داخلی عنصر را نشان میدهد، اما وقتی کاربر شروع به کشیدن میکند، محتوا جابهجا میشود وbackgroundContentظاهر میشود. هم محتوای عادی و همbackgroundContentبرای پردازش خودشان، محدودیتهای کامل ظرف مادر را دریافت میکنند.contentرویbackgroundContentکشیده میشود. در این مورد:-
backgroundContentبهعنوانIconبا رنگ پسزمینه براساسSwipeToDismissBoxValueپیادهسازی شده است: -
Blueهنگام کشیدنStartToEnd— روشن/خاموش کردن مورد فهرست کارها. Redهنگام تند کشیدنEndToStart— حذف کردن کار.- هیچچیز در پسزمینه
Settledنمایش داده نمیشود — وقتی روی مورد تند کشیده نمیشود، هیچچیز در پسزمینه نمایش داده نمیشود. - بههمین ترتیب،
Iconکه نمایش داده میشود با جهت تند کشیدن تطبیق پیدا میکند: - وقتی کار انجام شده باشد،
StartToEndنمادCheckBoxو وقتی کار انجام نشده باشد، نمادCheckBoxOutlineBlankرا نشان میدهد. EndToStartنماد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() ) } } }
نکات کلیدی درباره کد
-
mutableStateListOf(...)فهرست قابلمشاهدهای ایجاد میکند که میتواندTodoItemشیء را در خود جای دهد. وقتی موردی به این فهرست اضافه یا از آن برداشته میشود، «ترکیب» بخشهایی از واسط کاربر را که به آن بستگی دارد دوباره ترکیب میکند.- در
mutableStateListOf()، چهار شیءTodoItemبا شرحهای مربوطه مقداردهی اولیه میشوند: «پرداخت صورتحساب»، «خرید مواد غذایی»، «رفتن به باشگاه»، و «تهیه شام».
- در
LazyColumnفهرستی با پیمایش عمودی ازtodoItemsرا نمایش میدهد.-
onToggleDone = { todoItem -> ... }تابع برگشتی است که از درونTodoListItemفراخوانی میشود وقتی کاربر شیئی را بهعنوان انجامشده علامتگذاری میکند. ویژگیisItemDoneمربوط بهtodoItemرا بهروز میکند. چونtodoItemsیکmutableStateListOfاست، این تغییر باعث بازآرایی و بهروزرسانی واسط کاربر میشود. -
onRemove = { todoItem -> ... }یک تابع برگشتی است که وقتی کاربر مورد را برمیدارد راهاندازی میشود. این کارtodoItemخاص را از فهرستtodoItemsبرمیدارد. این کار باعث بازآرایی هم میشود و مورد از فهرست نمایشدادهشده برداشته میشود. - یک اصلاحگر
animateItemبه هرTodoListItemاعمال میشود تا وقتی مورد بسته شد،placementSpecاصلاحگر فراخوانده شود. این مورد حذف را بهصورت پویانمایی نشان میدهد، و همچنین ترتیب موارد دیگر در فهرست را تغییر میدهد.
نتیجه
ویدیو زیر عملکرد پایه کشیدن برای بستن را از گزیدههای قبلی نشان میدهد:
برای دیدن کد نمونه کامل، فایل منبع GitHub را ببینید.
مثال پیشرفته: پویانمایی رنگ پسزمینه در کشیدن
تکهکدهای زیر نشان میدهد چگونه میتوان آستانه موقعیتی را برای پویانمایی کردن رنگ پسزمینه عنصر در کشیدن اضافه کرد.
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.") } ) } } }
نکات کلیدی درباره کد
drawBehindمستقیماً در بوم پشت محتوایIconترکیبپذیر رسم میکند.drawRect()مستطیلی را روی بوم نقاشی میکند و کل محدوده قلمرو نقاشی را باColorمشخصشده پر میکند.
- هنگام تند کشیدن، رنگ پسزمینه مورد بااستفاده از
lerpبهآرامی تغییر میکند.- برای تند کشیدن از
StartToEnd، رنگ پسزمینه بهتدریج از خاکستری روشن به آبی تغییر میکند. - برای تند کشیدن از
EndToStart، رنگ پسزمینه بهتدریج از خاکستری روشن به قرمز تغییر میکند. - مقدار انتقال از یک رنگ به رنگ بعدی توسط
swipeToDismissBoxState.progressتعیین میشود.
- برای تند کشیدن از
OutlinedCardبین موارد فهرست جدایی دیداری ظریفی ایجاد میکند.
@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() ) } } }
نکات کلیدی درباره کد
- برای نکات کلیدی درباره این کد، به نکات کلیدی از بخش قبلی مراجعه کنید که یک تکهکد یکسان را توصیف میکند.
نتیجه
ویدیو زیر عملکرد پیشرفته با پسزمینه پویانماییشده رنگی را نشان میدهد:
برای دیدن کد نمونه کامل، فایل منبع GitHub را ببینید.