টিভির জন্য স্ক্রল করা যায় এমন লেআউট তৈরি করা

TV অ্যাপের ক্ষেত্রে, ব্রাউজিং অভিজ্ঞতা দক্ষ ফোকাস-ভিত্তিক নেভিগেশনের উপর নির্ভর করে। স্ট্যান্ডার্ড Compose Foundation লেজি লেআউট ব্যবহার করে, আপনি পারফর্ম্যান্ট ভার্টিক্যাল ও হরিজন্টাল তালিকা তৈরি করতে পারবেন যা অ্যাক্টিভ আইটেম ভিউতে রাখার জন্য অটোমেটিক ফোকাস-চালিত স্ক্রলিং ম্যানেজ করে।

টিভির জন্য অপ্টিমাইজ করা ডিফল্ট স্ক্রল আচরণ

Compose Foundation 1.7.0 থেকে শুরু করে, স্ট্যান্ডার্ড লেজি লেআউটে (যেমন LazyRow এবং LazyColumn) ফোকাস-পজিশনিং ফিচারের জন্য বিল্ট-ইন সহায়তা অন্তর্ভুক্ত থাকে। TV অ্যাপের জন্য ক্যাটালগ তৈরি করার ক্ষেত্রে এটি হল সাজেস্ট করা পদ্ধতি কারণ এটি ফোকাস করা আইটেমগুলিকে ব্যবহারকারীর জন্য দৃশ্যমান এবং স্বজ্ঞাতভাবে অবস্থান করতে সাহায্য করে।

একটি বেসিক স্ক্রলযোগ্য তালিকা প্রয়োগ করতে, স্ট্যান্ডার্ড লেজি কম্পোনেন্ট ব্যবহার করুন। এইসব কম্পোনেন্ট অটোমেটিক ডি-প্যাড নেভিগেশন ম্যানেজ করে এবং ফোকাস করা আইটেমকে ভিউতে নিয়ে আসে।

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-এর মাধ্যমে স্ক্রল বিহেভিয়ার কাস্টমাইজ করুন

আপনার ডিজাইনে যদি কোনও নির্দিষ্ট "পিভট" পয়েন্টের প্রয়োজন হয় (যেমন, ফোকাস করা আইটেমটি বাঁদিকের প্রান্ত থেকে ঠিক ৩০% দূরে রাখা), তাহলে আপনি BringIntoViewSpec ব্যবহার করে স্ক্রলিং ব্যবহার কাস্টমাইজ করতে পারেন। এটি পুরনো pivotOffsets ফাংশনালিটির জায়গায় এসেছে, যার মাধ্যমে আপনি ফোকাস করা আইটেমকে জায়গা দিতে ভিউপোর্ট কীভাবে স্ক্রল করবে তা ঠিক করতে পারবেন।

১. কাস্টম 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,
    )
}

২. কাস্টম স্পেসিফিকেশন প্রয়োগ করুন

পজিশনিং প্রয়োগ করতে হেল্পারের সাহায্যে আপনার লেআউট র‍্যাপ করুন। আপনার ক্যাটালগের বিভিন্ন সারি জুড়ে "ধারাবাহিক ফোকাস লাইন" তৈরি করার জন্য এটি উপযোগী।

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

৩. নির্দিষ্ট নেস্টেড লেআউটের জন্য অপ্ট-আউট করা

আপনার যদি কোনও নির্দিষ্ট নেস্টেড লেআউট থাকে যা আপনার কাস্টম পিভটের পরিবর্তে স্ট্যান্ডার্ড স্ক্রোলিং আচরণ ব্যবহার করা উচিত, তাহলে 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-এ টিভি-নির্দিষ্ট লেজি লেআউটগুলি স্ট্যান্ডার্ড কম্পোজ ফাউন্ডেশন লেআউটের পক্ষে বাতিল করা হয়েছে।

ডিপেন্ডেন্সি আপডেট

আপনার build.gradle-এ ভার্সন 1.7.0 বা তার পরের যেকোনও ভার্সন ব্যবহার করা হচ্ছে কিনা তা যাচাই করুন:

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

কম্পোনেন্ট ম্যাপিং

মাইগ্রেট করতে, আপনার ইমপোর্ট আপডেট করুন এবং আপনার কম্পোনেন্ট থেকে Tv প্রিফিক্স সরান:

অননুমোদিত টিভি কম্পোনেন্ট Compose Foundation রিপ্লেসমেন্ট
TvLazyRow LazyRow
TvLazyColumn LazyColumn
TvLazyHorizontalGrid LazyHorizontalGrid
TvLazyVerticalGrid LazyVerticalGrid
pivotOffsets BringIntoViewSpec (LocalBringIntoViewSpec-এর মাধ্যমে)