طرح‌بندی‌های قابل پیمایش برای تلویزیون ایجاد کنید

برای برنامه‌های تلویزیونی، تجربه مرور به ناوبری کارآمد مبتنی بر فوکوس متکی است. با استفاده از طرح‌بندی‌های تنبل استاندارد Compose Foundation، می‌توانید لیست‌های عمودی و افقی کارآمدی ایجاد کنید که به طور خودکار پیمایش مبتنی بر فوکوس را مدیریت می‌کنند تا موارد فعال در معرض دید باقی بمانند.

رفتار اسکرول پیش‌فرض برای تلویزیون بهینه شده است

با شروع Compose Foundation 1.7.0، طرح‌بندی‌های استاندارد lazy (مانند LazyRow و LazyColumn ) شامل پشتیبانی داخلی از ویژگی‌های موقعیت‌یابی focus هستند. این روش توصیه‌شده برای ساخت کاتالوگ برای برنامه‌های تلویزیونی است زیرا به کاربر کمک می‌کند تا موارد متمرکز را به صورت بصری قابل مشاهده و موقعیت‌یابی کند.

برای پیاده‌سازی یک لیست پیمایش‌پذیر اولیه، از کامپوننت‌های استاندارد lazy استفاده کنید. این کامپوننت‌ها به‌طور خودکار پیمایش با D-pad را مدیریت می‌کنند و آیتم مورد نظر را در معرض دید قرار می‌دهند.

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 می‌شود و به شما امکان می‌دهد دقیقاً تعریف کنید که چگونه viewport باید برای تطبیق با یک آیتم فوکوس شده پیمایش شود.

۱. یک BringIntoViewSpec سفارشی تعریف کنید

تابع کمکی composable زیر به شما امکان می‌دهد بر اساس کسرهای والد و فرزند، یک "محور" تعریف کنید. 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,
    )
}

۲. مشخصات سفارشی را اعمال کنید

طرح‌بندی‌های خود را با استفاده از ابزار کمکی برای اعمال موقعیت‌یابی، در هم بپیچید. این ابزار برای ایجاد یک «خط تمرکز ثابت» در ردیف‌های مختلف کاتالوگ شما مفید است.

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 { ... }
        }
    }
}

۳. برای طرح‌بندی‌های تو در تو خاص، انصراف دهید

If you have a specific nested layout that should use standard scrolling behavior instead of your custom pivot, provide the 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 خالی، رفتار پیش‌فرض فریم‌ورک را قادر می‌سازد تا کنترل را به دست گیرد.

مهاجرت از بنیاد تلویزیون به بنیاد آهنگسازی

طرح‌بندی‌های تنبل مخصوص تلویزیون در androidx.tv.foundation به نفع طرح‌بندی‌های استاندارد Compose Foundation منسوخ شده‌اند.

به‌روزرسانی‌های وابستگی

تأیید کنید که build.gradle شما از نسخه ۱.۷.۰ یا بالاتر برای موارد زیر استفاده می‌کند:

  • androidx.compose.foundation
  • androidx.compose.runtime

نگاشت اجزا

برای مهاجرت، ایمپورت‌های خود را به‌روزرسانی کنید و پیشوند Tv را از کامپوننت‌های خود حذف کنید:

کامپوننت تلویزیون منسوخ شده جایگزینی فونداسیون کامپوز
تی‌وی‌لیزی‌راو ردیف تنبل
ستون تنبل تلویزیون ستون تنبل
شبکه افقی تنبل تلویزیون (TVLazyHorizontalGrid) شبکه افقی تنبل
شبکه عمودی تی‌وی-لازی شبکه عمودی تنبل
pivotOffsets BringIntoViewSpec (از طریق LocalBringIntoViewSpec)