بالنسبة إلى تطبيقات التلفزيون، تعتمد تجربة التصفّح على التنقّل الفعّال المستند إلى التركيز. باستخدام تنسيقات العرض الكسولة العادية في 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 العادية.
تحديثات التبعيات
تأكَّد من أنّ build.gradle يستخدم الإصدار 1.7.0 أو إصدارًا أحدث من أجل:
androidx.compose.foundationandroidx.compose.runtime
ربط المكوّنات
لإجراء عملية النقل، عدِّل عمليات الاستيراد وأزِل البادئة Tv من المكوّنات:
| مكوّن التلفزيون المتوقّف نهائيًا | Compose Foundation replacement |
|---|---|
| TvLazyRow | LazyRow |
| TvLazyColumn | LazyColumn |
| TvLazyHorizontalGrid | LazyHorizontalGrid |
| TvLazyVerticalGrid | LazyVerticalGrid |
| pivotOffsets | BringIntoViewSpec (عبر LocalBringIntoViewSpec) |