يسمح المكوّن 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
callback بعد الانتهاء من التفاعل مع العنصر. يعالج ملف الاستدعاء الإجراءات المختلفة المحتملة. يعرض الإجراء المُعاد برمجيًا قيمة برمجية تشكل تعبيرًا منطقيًا تحدّد للمكوّن ما إذا كان يجب عرض رسوم متحركة لإغلاق التطبيق. في هذه الحالة:- إذا تم التمرير سريعًا للعنصر من البداية إلى النهاية، يتم استدعاء دالة
onToggleDone
لامدا مع تمريرtodoItem
الحالية. ويتوافق ذلك مع تعديل مادة المهام. - إذا تم التمرير سريعًا للعنصر من النهاية إلى البداية، يتمّ استدعاء دالة
onRemove
lambda، مع تمريرtodoItem
الحالية. ويؤدي ذلك إلى حذف مهمة جدول الأعمال. it != StartToEnd
: يعرض هذا السطر القيمةtrue
إذا لم يكن اتجاه التمرير هوStartToEnd
، ويعرض القيمة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 للحصول على نموذج الرمز البرمجي الكامل.