بالنسبة إلى تطبيقات التلفزيون، تعتمد تجربة التصفّح على التنقّل الفعّال المستند إلى التركيز. باستخدام التصاميم الكسولة العادية في Compose Foundation، يمكنك إنشاء قوائم عمودية وأفقية عالية الأداء تتعامل تلقائيًا مع الانتقال المستند إلى التركيز لإبقاء العناصر النشطة في العرض.
تحسين السلوك التلقائي للتمرير ليتناسب مع شاشات التلفزيون
بدءًا من الإصدار 1.7.0 من Compose Foundation، تتضمّن التصاميم العادية ذات التحميل الكسول (مثل LazyRow وLazyColumn) دعمًا مدمجًا لميزات تحديد موضع التركيز. هذه هي الطريقة المقترَحة لإنشاء كتالوجات لتطبيقات التلفزيون، لأنّها تساعد في إبقاء العناصر التي تم التركيز عليها مرئية وموضّحة بشكل بديهي للمستخدم.
لتنفيذ قائمة أساسية قابلة للتمرير، استخدِم المكوّنات العادية التي يتم تحميلها عند الحاجة. تتعامل هذه المكوّنات تلقائيًا مع التنقّل باستخدام لوحة التحكّم الاتجاهية وتعرض العنصر الذي تم التركيز عليه.
import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.items @Composable fun MovieCatalog(movies: List<Movie>) { LazyRow { items(movies) { movie -> MovieCard( movie = movie, onClick = { /* Handle click */ } ) } } }
تخصيص سلوك التمرير باستخدام BringIntoViewSpec
إذا كان تصميمك يتطلّب نقطة "محورية" معيّنة (على سبيل المثال، إبقاء العنصر الذي تم التركيز عليه على بُعد% 30 بالضبط من الحافة اليسرى)، يمكنك تخصيص سلوك التمرير باستخدام BringIntoViewSpec. يحلّ هذا الخيار محلّ وظيفة pivotOffsets القديمة من خلال السماح لك بتحديد الطريقة التي يجب أن يتم بها تمرير إطار العرض
لاستيعاب عنصر تم التركيز عليه.
1. تحديد BringIntoViewSpec مخصّص
تتيح لك الدالة البرمجية القابلة للإنشاء المساعدة التالية تحديد "نقطة محورية" استنادًا إلى كسور الأب والابن. تحدّد السمة parentFraction موضع ظهور العنصر في الحاوية، بينما تحدّد السمة childFraction الجزء من العنصر الذي يجب أن يتطابق مع هذا الموضع.
@OptIn(ExperimentalFoundationApi::class) @Composable fun PositionFocusedItemInLazyLayout( parentFraction: Float = 0.3f, childFraction: Float = 0f, content: @Composable () -> Unit, ) { val bringIntoViewSpec = remember(parentFraction, childFraction) { object : BringIntoViewSpec { override fun calculateScrollDistance( offset: Float, // Item's initial position size: Float, // Item's size containerSize: Float // Container's size ): Float { // Calculate the offset position of the item's leading edge. val initialTargetForLeadingEdge = parentFraction * containerSize - (childFraction * size) // If the item fits in the container, and scrolling would cause // its trailing edge to be clipped, adjust targetForLeadingEdge // to prevent over-scrolling near the end of list. val targetForLeadingEdge = if (size <= containerSize && (containerSize - initialTargetForLeadingEdge) < size) { // If clipped, align the item's trailing edge with the // container's trailing edge. containerSize - size } else { initialTargetForLeadingEdge } // Return scroll distance relative to initial item position. return offset - targetForLeadingEdge } } } // Apply the spec to all scrollables in the hierarchy CompositionLocalProvider( LocalBringIntoViewSpec provides bringIntoViewSpec, content = content, ) }
2. تطبيق المواصفات المخصّصة
لفّ تنسيقاتك بالدالة المساعدة لتطبيق تحديد الموضع. ويفيد ذلك في إنشاء "خط تركيز متسق" على مستوى الصفوف المختلفة في الكتالوج.
PositionFocusedItemInLazyLayout( parentFraction = 0.3f, // Pivot 30% from the edge childFraction = 0.5f // Center of the item aligns with the pivot ) { LazyColumn { items(sectionList) { section -> // This row and its items will respect the 30% pivot LazyRow { /* ... */ } } } }
3- إيقاف ميزة "التخطيطات المتداخلة" المحدّدة
إذا كان لديك تنسيق متداخل معيّن يجب أن يستخدم سلوك التمرير العادي بدلاً من محور التدوير المخصّص، قدِّم DefaultBringIntoViewSpec:
private val DefaultBringIntoViewSpec = object : BringIntoViewSpec {} PositionFocusedItemInLazyLayout { LazyColumn { item { // This row will ignore the custom pivot and use default behavior CompositionLocalProvider(LocalBringIntoViewSpec provides DefaultBringIntoViewSpec) { LazyRow { /* ... */ } } } } }
في الواقع، يؤدي تمرير قيمة فارغة إلى السمة BringIntoViewSpec إلى تفعيل السلوك التلقائي لإطار العمل.
نقل البيانات من TV Foundation إلى Compose Foundation
تم إيقاف نهائيًا التنسيقات الكسولة الخاصة بالتلفزيون في androidx.tv.foundation، واستبدالها بتنسيقات Compose Foundation العادية.
تعديلات على التبعيات
تأكَّد من أنّ الإصدار 1.7.0 أو إصدار أحدث من build.gradle مستخدَم في ما يلي:
androidx.compose.foundationandroidx.compose.runtime
ربط المكوّنات
لإجراء عملية النقل، عدِّل عمليات الاستيراد وأزِل البادئة Tv من مكوّناتك باتّباع الخطوات التالية:
| مكوّن التلفزيون المتوقّف نهائيًا | Compose Foundation replacement |
|---|---|
| TvLazyRow | LazyRow |
| TvLazyColumn | LazyColumn |
| TvLazyHorizontalGrid | LazyHorizontalGrid |
| TvLazyVerticalGrid | LazyVerticalGrid |
| pivotOffsets | BringIntoViewSpec (via LocalBringIntoViewSpec) |