عنصر 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را فراخوانی میکند. بدنه فراخوانی برگشتی کنشهای احتمالی مختلف را مدیریت میکند. فراخوانی برگشتی یک مقدار بولی برمیگرداند که به مؤلفه میگوید آیا باید پویانمایی بستن را نمایش دهد یا نه. در این مورد:- اگر مورد از ابتدا به انتها تند کشیده شود،
onToggleDonelambda را فراخوانی میکند وtodoItemفعلی را ارسال میکند. این با بهروزرسانی مورد کارها مطابقت دارد. - اگر مورد از انتها به ابتدا تند کشیده شود،
onRemoveلامبدا را فراخوانی میکند،todoItemفعلی را رد میکند. این کار با حذف کردن مورد فهرست کارهای انجامدادنی مطابقت دارد. it != StartToEnd: اگر جهت تند کشیدنStartToEndنباشد، این خطtrueرا برمیگرداند، و درغیراینصورتfalseرا برمیگرداند. برگرداندنfalseاز ناپدید شدن فوریSwipeToDismissBoxپساز تند کشیدن «تغییر وضعیت انجام شد» جلوگیری میکند، و امکان تأیید بصری یا پویانمایی را فراهم میکند.
- اگر مورد از ابتدا به انتها تند کشیده شود،
-
SwipeToDismissBoxتعاملات تند کشیدن افقی را در هر مورد فعال میکند. در حالت استراحت، محتوای داخلی مؤلفه را نشان میدهد، اما وقتی کاربر تند کشیدن را شروع میکند، محتوا جابهجا میشود وbackgroundContentظاهر میشود. Both the normal content and thebackgroundContentget the full constraints of the parent container to render themselves in.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شیء را در خود نگه دارد. وقتی موردی به این فهرست اضافه یا از آن برداشته میشود، Compose بخشهایی از واسط کاربر را که به آن وابسته است بازترکیب میکند.- Inside
mutableStateListOf(), fourTodoItemobjects are initialized with their respective descriptions: "Pay bills", "Buy groceries", "Go to gym", and "Get dinner".
- Inside
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 را ببینید.