يتيح مكوّن SwipeToDismissBox للمستخدم إغلاق عنصر أو تعديله من خلال التمرير سريعًا إلى اليمين أو اليسار.
مساحة عرض واجهة برمجة التطبيقات
استخدِم الدالة المركّبة SwipeToDismissBox لتنفيذ الإجراءات التي يتم تفعيلها
من خلال إيماءات التمرير السريع. تشمل المَعلمات الرئيسية ما يلي:
state: حالةSwipeToDismissBoxStateالتي تم إنشاؤها لتخزين القيمة الناتجة عن العمليات الحسابية على عنصر التمرير السريع، والتي تؤدي إلى تشغيل الأحداث عند إنتاجها.-
backgroundContent: دالة مركّبة قابلة للتخصيص يتم عرضها خلف محتوى العنصر الذي يظهر عند التمرير سريعًا على المحتوى
مثال أساسي: التعديل أو الإغلاق عند التمرير السريع
The snippets in this example show a swipe implementation that either updates the item when swiped from start to end, or dismisses the item when swiped from end to start.
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( painter = rememberVectorPainter(if (todoItem.isItemDone) AppIcons.CheckBox else AppIcons.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( painter = rememberVectorPainter(AppIcons.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بعد انتهاء التفاعل مع العنصر. يعالج نص رد الاتصال الإجراءات المختلفة الممكنة. تعرض دالة الاستدعاء قيمة منطقية تخبر المكوّن بما إذا كان يجب عرض تأثير متحرك للإغلاق. في هذه الحالة:- إذا تم تمرير العنصر من البداية إلى النهاية، يتم استدعاء دالة lambda
onToggleDone، مع تمريرtodoItemالحالي. يتوافق هذا مع تحديث عنصر قائمة المهام. - إذا تم تمرير العنصر من النهاية إلى البداية، يتم استدعاء دالة lambda
onRemove، مع تمريرtodoItemالحالي. يتوافق هذا مع حذف عنصر قائمة المهام. -
it != StartToEnd: يعرض هذا السطر القيمةtrueإذا لم يكن اتجاه التمرير سريعًاStartToEnd، والقيمةfalseفي الحالات الأخرى. يؤدي عرض القيمةfalseإلى منع اختفاءSwipeToDismissBoxفورًا بعد التمرير السريع "تبديل الحالة إلى تم"، ما يتيح تأكيدًا مرئيًا أو حركة.
- إذا تم تمرير العنصر من البداية إلى النهاية، يتم استدعاء دالة lambda
- يتيح
SwipeToDismissBoxالتفاعل من خلال التمرير السريع أفقيًا على كل عنصر. في وضع السكون، يعرض المكوّن المحتوى الداخلي، ولكن عندما يبدأ المستخدم بالتمرير السريع، يتم إبعاد المحتوى ويظهرbackgroundContent. يحصل كل من المحتوى العادي وbackgroundContentعلى القيود الكاملة للحاوية الرئيسية لعرض أنفسهم فيها. يتم رسمcontentفوقbackgroundContent. في هذه الحالة:- يتم تنفيذ
backgroundContentكـIconبلون خلفية يستند إلىSwipeToDismissBoxValue: Blueعند التمرير سريعًا علىStartToEnd: تبديل حالة مهمةRedعند التمرير سريعًا علىEndToStart، يتم حذف مهمة.- لا يتم عرض أي شيء في الخلفية لـ
Settled— عندما لا يتم تمرير العنصر، لا يتم عرض أي شيء في الخلفية. - وبالمثل، يتكيّف
Iconالمعروض مع اتجاه التمرير السريع: - يعرض "
StartToEnd" الرمزCheckBoxعندما تكون المهمة مكتملة، والرمزCheckBoxOutlineBlankعندما تكون غير مكتملة. - يعرض "
EndToStart" رمز "Delete".
- يتم تنفيذ
@Composable 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 إنشاء أجزاء واجهة المستخدم التي تعتمد عليها.- داخل
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( painter = rememberVectorPainter(if (todoItem.isItemDone) AppIcons.CheckBox else AppIcons.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( painter = rememberVectorPainter(AppIcons.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 للحصول على الرمز النموذجي الكامل.