Wear OS এর জন্য রচনা সহ তালিকা


Wear OS ডিভাইসে তালিকা ব্যবহারকারীদের বিভিন্ন বিকল্পের মধ্য থেকে কোনো একটি আইটেম বেছে নিতে সাহায্য করে।

অনেক Wear OS ডিভাইসে গোলাকার স্ক্রিন ব্যবহার করা হয়, যার ফলে স্ক্রিনের ওপর ও নিচের দিকের লিস্ট আইটেমগুলো দেখতে অসুবিধা হয়। এই কারণে, Wear OS-এর জন্য Compose-এ LazyColumn ক্লাসের TransformingLazyColumn নামক একটি সংস্করণ অন্তর্ভুক্ত করা হয়েছে, যা স্কেলিং এবং মর্ফিং অ্যানিমেশন সমর্থন করে। আইটেমগুলো যখন প্রান্তের দিকে চলে যায়, তখন সেগুলো ছোট হয়ে যায় এবং ধীরে ধীরে মিলিয়ে যায়।

প্রস্তাবিত স্কেলিং এবং স্ক্রোলিং ইফেক্টগুলো প্রয়োগ করতে:

  1. স্ক্রিনে আইটেমটি স্ক্রল করার সময় Compose-কে উচ্চতার পরিবর্তন গণনা করার সুযোগ দিতে Modifier.transformedHeight ব্যবহার করুন।
  2. আইটেমের বিষয়বস্তু ছোট করা সহ ভিজ্যুয়াল ইফেক্টগুলো প্রয়োগ করতে transformation = SurfaceTransformation(transformationSpec) ব্যবহার করুন।
  3. যেসব কম্পোনেন্ট প্যারামিটার হিসেবে transformation গ্রহণ করে না, যেমন Text সেগুলোর জন্য একটি কাস্টম TransformationSpec ব্যবহার করুন।

নিম্নলিখিত অ্যানিমেশনটি দেখায় কিভাবে একটি তালিকার উপাদান স্ক্রিনের উপরে এবং নীচে যাওয়ার সময় তার আকার ও আকৃতি পরিবর্তন করে:

নিম্নলিখিত কোড স্নিপেটটি দেখায় কিভাবে TransformingLazyColumn লেআউট ব্যবহার করে একটি তালিকা তৈরি করা যায়, যার বিষয়বস্তু বিভিন্ন Wear OS স্ক্রিনের আকারে চমৎকার দেখায়

এই কোড স্নিপেটটিতে minimumVerticalContentPadding মডিফায়ারটির ব্যবহারও দেখানো হয়েছে, যা লিস্টের উপরে ও নীচে সঠিক প্যাডিং প্রয়োগ করার জন্য লিস্ট আইটেমগুলোতে সেট করতে হয়।

স্ক্রোল ইন্ডিকেটর দেখানোর জন্য, ScreenScaffold এবং TransformingLazyColumn এর মধ্যে columnState শেয়ার করুন:

val columnState = rememberTransformingLazyColumnState()
val transformationSpec = rememberTransformationSpec()
ScreenScaffold(
    scrollState = columnState
) { contentPadding ->
    TransformingLazyColumn(
        state = columnState,
        contentPadding = contentPadding
    ) {
        item {
            ListHeader(
                modifier = Modifier
                    .fillMaxWidth()
                    .transformedHeight(this, transformationSpec)
                    .minimumVerticalContentPadding(ListHeaderDefaults.minimumTopListContentPadding),
                transformation = SurfaceTransformation(transformationSpec)
            ) {
                Text(text = "Header")
            }
        }
        // ... other items
        item {
            Button(
                modifier = Modifier
                    .fillMaxWidth()
                    .transformedHeight(this, transformationSpec)
                    .minimumVerticalContentPadding(ButtonDefaults.minimumVerticalListContentPadding),
                transformation = SurfaceTransformation(transformationSpec),
                onClick = { /* ... */ },
                icon = {
                    Icon(
                        imageVector = Icons.Default.Build,
                        contentDescription = "build",
                    )
                },
            ) {
                Text(
                    text = "Build",
                    maxLines = 1,
                    overflow = TextOverflow.Ellipsis,
                )
            }
        }
    }
}

একটি স্ন্যাপ-অ্যান্ড-ফ্লিং এফেক্ট যোগ করুন

স্ন্যাপিং নিশ্চিত করে যে, যখন কোনো ব্যবহারকারী স্ক্রল বা ফ্লিং জেসচার শেষ করেন, তখন তালিকাটির একটি আইটেম একটি নির্দিষ্ট বিন্দুতে, সাধারণত স্ক্রিনের কেন্দ্রে, নির্ভুলভাবে অবস্থান করে স্থির হয়। গোলাকার স্ক্রিনে, যেখানে আইটেমগুলো কেন্দ্র থেকে দূরে সরে গেলে আকার ও আকৃতি পরিবর্তন করে, সেখানে সবচেয়ে প্রাসঙ্গিক আইটেমটি যেন সর্বোত্তম দেখার জায়গায় সম্পূর্ণ দৃশ্যমান ও পাঠযোগ্য থাকে, তা নিশ্চিত করতে স্ন্যাপিং বিশেষভাবে কার্যকর।

স্ন্যাপ-অ্যান্ড-ফ্লিং আচরণ যোগ করতে, flingBehavior প্যারামিটারটিকে TransformingLazyColumnDefaults.snapFlingBehavior(columnState) -এ সেট করুন। ফিজিক্যাল ক্রাউন বা বেজেল ব্যবহার করার সময় একটি সামঞ্জস্যপূর্ণ অভিজ্ঞতার জন্য, rotaryScrollableBehavior টিকেও RotaryScrollableDefaults.snapBehavior(columnState) ব্যবহার করে এর সাথে মিলিয়ে সেট করুন।

val columnState = rememberTransformingLazyColumnState()
ScreenScaffold(scrollState = columnState) { contentPadding ->
    TransformingLazyColumn(
        state = columnState,
        flingBehavior = TransformingLazyColumnDefaults.snapFlingBehavior(columnState),
        rotaryScrollableBehavior = RotaryScrollableDefaults.snapBehavior(columnState)
    ) {
        // ...
        // ...
    }
}

বিপরীত বিন্যাস

ডিফল্টরূপে, একটি স্ক্রোলযোগ্য তালিকা তার উপরের প্রান্তে স্থির থাকে। যদি কোনো ব্যবহারকারী একটি সাধারণ তালিকার একেবারে নিচে স্ক্রোল করে যান এবং শেষে একটি নতুন আইটেম যুক্ত করা হয়, তবে তালিকাটি বর্তমান আইটেমটির উপর ব্যবহারকারীর দৃষ্টি বজায় রাখে। উদাহরণস্বরূপ, যদি ব্যবহারকারী স্ক্রিনের নিচের দিকে ১০ নম্বর আইটেমটি দেখে থাকেন এবং ১১ নম্বর আইটেমটি যুক্ত করা হয়, তবে দৃষ্টি ১০ নম্বর আইটেমটির উপরেই নিবদ্ধ থাকবে এবং ১১ নম্বর আইটেমটি বর্তমান দৃশ্যের নিচে স্ক্রিনের বাইরে প্রদর্শিত হবে।

মেসেজিং অ্যাপ্লিকেশন বা লাইভ লগের মতো ব্যবহারের ক্ষেত্রে, এই আচরণটি সাধারণত কাম্য নয়। যখন নতুন আইটেম আসে, ব্যবহারকারীরা যদি তালিকার একেবারে নিচে থাকেন, তবে তারা সাধারণত সর্বশেষ বিষয়বস্তুটি সঙ্গে সঙ্গে দেখতে চান। যদি একসাথে অনেকগুলো আইটেম আসে, তবে তালিকাটির উচিত একেবারে নিচের সর্বশেষ আইটেমটি প্রদর্শন করা (যার অর্থ হলো, ব্যবহারকারী উপরে স্ক্রল না করা পর্যন্ত মাঝের কিছু আইটেম হয়তো মোটেই প্রদর্শিত হবে না)।

এইসব ব্যবহারের ক্ষেত্রকে সমর্থন করার জন্য, TransformingLazyColumn আপনাকে reverseLayout = true সেট করে লেআউটটি উল্টে দেওয়ার সুযোগ দেয়। এর ফলে তালিকার অ্যাঙ্করটি উপরের প্রান্ত থেকে নিচের প্রান্তে স্থানান্তরিত হয়।

সুবিধার জন্য, reverseLayout = true সেট করলে আইটেমগুলোর দৃশ্যমান ক্রম এবং স্ক্রোলিং জেসচারের দিকও উল্টে যায়:

  • আইটেমগুলো নিচ থেকে উপরের দিকে সাজানো থাকে, অর্থাৎ ইনডেক্স ০ স্ক্রিনের নিচে প্রদর্শিত হয়।
  • উপরে স্ক্রল করলে উচ্চতর সূচকের আইটেমগুলো দেখা যায়।

রিভার্স লেআউটের সাথে স্ন্যাপ-অ্যান্ড-ফ্লিং বিহেভিয়ার যোগ করতে, আপনি নিচের কোড স্নিপেটে দেখানো অনুযায়ী flingBehavior এবং rotaryScrollableBehavior একত্রিত করতে পারেন:

val columnState = rememberTransformingLazyColumnState()
val transformationSpec = rememberTransformationSpec()
ScreenScaffold(scrollState = columnState) { contentPadding ->
    TransformingLazyColumn(
        state = columnState,
        contentPadding = contentPadding,
        reverseLayout = true,
        modifier = Modifier.fillMaxWidth()
    ) {
        items(10) { index ->
            Button(
                label = {
                    Text(
                        text = "Item ${index + 1}"
                    )
                },
                onClick = {},
                modifier = Modifier
                    .fillMaxWidth()
                    .transformedHeight(this, transformationSpec)
                    .minimumVerticalContentPadding(ButtonDefaults.minimumVerticalListContentPadding),
                transformation = SurfaceTransformation(transformationSpec)
            )
        }
        item {
            // With reverseLayout = true, the last item declared appears at the top.
            ListHeader(
                modifier = Modifier
                    .fillMaxWidth()
                    .transformedHeight(this, transformationSpec)
                    .minimumVerticalContentPadding(ListHeaderDefaults.minimumTopListContentPadding),
                transformation = SurfaceTransformation(transformationSpec)
            ) {
                Text("Header")
            }
        }
    }
}

নিচের ছবিগুলোতে একটি সাধারণ তালিকা এবং একটি বিপরীত তালিকার মধ্যে পার্থক্য দেখানো হয়েছে:

সাধারণ লেআউট সহ একটি TransformingLazyColumn, যা শীর্ষে আইটেম ১ এবং বাকি আইটেমগুলো আরোহী ক্রমে প্রদর্শন করে।
চিত্র ১. একটি আদর্শ তালিকা বিন্যাস যেখানে বিষয়বস্তু উপর থেকে নিচে পূর্ণ হয়।
বিপরীত লেআউট সহ একটি TransformingLazyColumn, যা আইটেম ১-কে নীচে এবং আইটেমগুলিকে অবরোহী ক্রমে উপরের দিকে দেখায়।
চিত্র ২. একটি বিপরীত তালিকা বিন্যাস যেখানে বিষয়বস্তু নিচ থেকে উপরের দিকে পূরণ হয়।
{% হুবহু %} {% endverbatim %} {% হুবহু %} {% endverbatim %}