يوفّر المعدّلان
verticalScroll
وhorizontalScroll
أبسط طريقة للسماح للمستخدم بالتمرير في عنصر عندما تكون حدود محتواه أكبر من قيود الحد الأقصى لحجمه. باستخدام المعدِّلَين verticalScroll وhorizontalScroll، لن تحتاج إلى
ترجمة المحتوى أو إزاحته.
@Composable private fun ScrollBoxes() { Column( modifier = Modifier .background(Color.LightGray) .size(100.dp) .verticalScroll(rememberScrollState()) ) { repeat(10) { Text("Item $it", modifier = Modifier.padding(2.dp)) } } }
تتيح لك السمة ScrollState تغيير موضع الانتقال أو الحصول على حالته الحالية. لإنشاء هذه المَعلمة باستخدام المَعلمات التلقائية، استخدِم rememberScrollState().
@Composable private fun ScrollBoxesSmooth() { // Smoothly scroll 100px on first composition val state = rememberScrollState() LaunchedEffect(Unit) { state.animateScrollTo(100) } Column( modifier = Modifier .background(Color.LightGray) .size(100.dp) .padding(horizontal = 8.dp) .verticalScroll(state) ) { repeat(10) { Text("Item $it", modifier = Modifier.padding(2.dp)) } } }
معدِّل المنطقة القابلة للتمرير
يُعدّ المُعدِّل scrollableArea وحدة أساسية لإنشاء حاويات مخصّصة قابلة للتمرير. ويوفّر تجريدًا عالي المستوى على المعدِّل scrollable، ويتعامل مع المتطلبات الشائعة مثل تفسير دلتا الإيماءات واقتصاص المحتوى وتأثيرات تجاوز حد التمرير.
على الرغم من استخدام scrollableArea لعمليات التنفيذ المخصّصة، يجب بشكل عام
تفضيل الحلول الجاهزة مثل verticalScroll أو horizontalScroll
أو الدوال المركّبة مثل LazyColumn لقوائم الانتقال العادية. هذه المكوّنات ذات المستوى الأعلى هي أبسط لحالات الاستخدام الشائعة، ويتم إنشاؤها باستخدام scrollableArea.
الفرق بين معدِّلَي scrollableArea وscrollable
يكمن الاختلاف الرئيسي بين scrollableArea وscrollable في كيفية
تفسير إيماءات الانتقال التي ينفّذها المستخدم:
-
scrollable(الفرق الأولي): يعكس الفرق مباشرةً الحركة المادية لإدخال المستخدم (مثل سحب المؤشر) على الشاشة. scrollableArea(دلتا موجّهة نحو المحتوى): يتم عكسdeltaدلاليًا لتمثيل التغيير المحدّد في موضع الانتقال لجعل المحتوى يبدو وكأنه يتحرك مع إيماءة المستخدم، والتي عادةً ما تكون عكس حركة المؤشر.
يمكنك التفكير في الأمر على النحو التالي: يخبرك scrollable بكيفية تحرك المؤشر، بينما
يترجم scrollableArea حركة المؤشر إلى كيفية تحرك المحتوى
ضمن طريقة عرض نموذجية قابلة للتمرير. هذا الانعكاس هو السبب في أنّ scrollableArea
يبدو أكثر طبيعية عند تنفيذ حاوية عادية قابلة للتمرير.
يلخّص الجدول التالي علامات الفرق في السيناريوهات الشائعة:
إجراء تفاعلي من المستخدم |
تم الإبلاغ عن الفرق إلى " |
تم إبلاغ " |
|---|---|---|
يتحرّك المؤشر للأعلى |
سلبية |
إيجابية |
يتحرّك المؤشر للأسفل |
إيجابية |
سلبية |
يتحرّك المؤشر إلى اليسار |
سلبية |
موجبة (سالبة للغات المكتوبة من اليمين إلى اليسار) |
يتحرّك المؤشر إلى اليمين |
إيجابية |
قيمة سالبة (موجبة للغات المكتوبة من اليمين إلى اليسار) |
(*) ملاحظة حول علامة دلتا في scrollableArea: علامة دلتا من
scrollableArea ليست مجرد انعكاس بسيط. وتأخذ في الاعتبار بذكاء ما يلي:
- الاتجاه: عمودي أو أفقي
-
LayoutDirection: من اليمين إلى اليسار أو من اليسار إلى اليمين (مهم بشكل خاص للتمرير الأفقي). - علامة
reverseScrolling: تشير إلى ما إذا كان اتجاه الانتقال معكوسًا.
بالإضافة إلى عكس دلتا التمرير، يقتطع scrollableArea أيضًا
المحتوى إلى حدود التنسيق ويتعامل مع عرض تأثيرات
تجاوز حد التمرير. ويستخدم تلقائيًا التأثير الذي يوفّره LocalOverscrollFactory.
يمكنك تخصيص هذه الميزة أو إيقافها باستخدام التحميل الزائد scrollableArea الذي يقبل مَعلمة OverscrollEffect.
حالات استخدام المُعدِّل scrollableArea
يجب استخدام المُعدِّل scrollableArea عندما تحتاج إلى إنشاء مكوّن مخصّص للتمرير لا يوفّره المُعدِّلان horizontalScroll أو verticalScroll أو التنسيقات الكسولة بشكل كافٍ. ويشمل ذلك غالبًا الحالات التي تتضمّن ما يلي:
- منطق التنسيق المخصّص: عندما يتغيّر ترتيب العناصر ديناميكيًا استنادًا إلى موضع الانتقال
- مؤثرات بصرية فريدة: تطبيق عمليات التحويل أو تغيير الحجم أو مؤثرات أخرى على العناصر الفرعية أثناء الانتقال للأعلى أو للأسفل
- التحكّم المباشر: الحاجة إلى التحكّم الدقيق في آليات الانتقال
بما يتجاوز ما يوفّره
verticalScrollأو التنسيقات الكسولة.
إنشاء قوائم مخصّصة تشبه العجلة باستخدام scrollableArea
يوضّح النموذج التالي كيفية استخدام scrollableArea لإنشاء قائمة عمودية مخصّصة يتم فيها تصغير العناصر كلما ابتعدت عن المركز، ما يؤدي إلى إنشاء تأثير مرئي "يشبه العجلة". هذا النوع من التحويلات التي تعتمد على الانتقال هو
حالة استخدام مثالية لـ scrollableArea.
scrollableArea
@Composable private fun ScrollableAreaSample() { // ... Layout( modifier = Modifier .size(150.dp) .scrollableArea(scrollState, Orientation.Vertical) .background(Color.LightGray), // ... ) { measurables, constraints -> // ... // Update the maximum scroll value to not scroll beyond limits and stop when scroll // reaches the end. scrollState.maxValue = (totalHeight - viewportHeight).coerceAtLeast(0) // Position the children within the layout. layout(constraints.maxWidth, viewportHeight) { // The current vertical scroll position, in pixels. val scrollY = scrollState.value val viewportCenterY = scrollY + viewportHeight / 2 var placeableLayoutPositionY = 0 placeables.forEach { placeable -> // This sample applies a scaling effect to items based on their distance // from the center, creating a wheel-like effect. // ... // Place the item horizontally centered with a layer transformation for // scaling to achieve wheel-like effect. placeable.placeRelativeWithLayer( x = constraints.maxWidth / 2 - placeable.width / 2, // Offset y by the scroll position to make placeable visible in the viewport. y = placeableLayoutPositionY - scrollY, ) { scaleX = scaleFactor scaleY = scaleFactor } // Move to the next item's vertical position. placeableLayoutPositionY += placeable.height } } } } // ...
معدِّل قابل للتمرير
يختلف المُعدِّل
scrollable
عن مُعدِّلات الانتقال في أنّ scrollable يرصد
إيماءات الانتقال ويسجّل الاختلافات، ولكنّه لا يعوّض المحتوى
تلقائيًا. ويتم تفويض ذلك بدلاً من ذلك إلى المستخدم من خلال
ScrollableState
، وهو مطلوب لكي يعمل هذا المُعدِّل بشكل صحيح.
عند إنشاء ScrollableState، يجب توفير دالة consumeScrollDelta
سيتم استدعاؤها في كل خطوة من خطوات الانتقال (عن طريق إدخال الإيماءات أو الانتقال السلس
أو التمرير السريع) مع الفرق بالبكسل. يجب أن تعرض هذه الدالة
مقدار مسافة الانتقال المستهلكة، لضمان نشر الحدث بشكل صحيح
في الحالات التي توجد فيها عناصر متداخلة تحتوي على المُعدِّل scrollable.
يرصد المقتطف التالي الإيماءات ويعرض قيمة رقمية للإزاحة، ولكنه لا يزيح أي عناصر:
@Composable private fun ScrollableSample() { // actual composable state var offset by remember { mutableFloatStateOf(0f) } Box( Modifier .size(150.dp) .scrollable( orientation = Orientation.Vertical, // Scrollable state: describes how to consume // scrolling delta and update offset state = rememberScrollableState { delta -> offset += delta delta } ) .background(Color.LightGray), contentAlignment = Alignment.Center ) { Text(offset.toString()) } }
التطبيقات المقترَحة لك
- ملاحظة: يتم عرض نص الرابط عندما يكون JavaScript غير مفعَّل
- التعرّف على الإيماءات
- نقل بيانات
CoordinatorLayoutإلى Compose - استخدام طرق العرض في Compose