কাস্টম লেআউট

কম্পোজে, UI এলিমেন্টগুলোকে কম্পোজেবল ফাংশন দ্বারা উপস্থাপন করা হয়, যেগুলো কল করা হলে UI-এর একটি অংশ তৈরি করে, যা পরে একটি UI ট্রি-তে যুক্ত হয় এবং স্ক্রিনে রেন্ডার করা হয়। প্রতিটি UI এলিমেন্টের একটি প্যারেন্ট এবং সম্ভাব্য অনেকগুলো চাইল্ড থাকে। প্রতিটি এলিমেন্ট তার প্যারেন্টের মধ্যে অবস্থিত থাকে, যা একটি (x, y) অবস্থান দ্বারা নির্দিষ্ট করা হয়, এবং এর একটি আকার থাকে, যা একটি প্রস্থ ( width ) এবং একটি height দ্বারা নির্দিষ্ট করা হয়।

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

UI ট্রি-তে প্রতিটি নোড সাজানো একটি তিন ধাপের প্রক্রিয়া। প্রতিটি নোডকে অবশ্যই:

  1. যেকোনো শিশুদের পরিমাপ করুন
  2. এর নিজস্ব আকার নির্ধারণ করুন
  3. এর সন্তানদের রাখুন
নোড লেআউটের তিনটি ধাপ: চাইল্ড নোডগুলোর পরিমাপ নেওয়া, আকার নির্ধারণ করা, চাইল্ড নোডগুলোর অবস্থান ঠিক করা।
চিত্র ১। নোড লেআউটের তিনটি ধাপ হলো চাইল্ড নোডগুলোর পরিমাপ করা, আকার নির্ধারণ করা এবং চাইল্ড নোডগুলোকে সঠিক স্থানে স্থাপন করা।

স্কোপের ব্যবহার নির্ধারণ করে দেয় যে আপনি কখন আপনার চাইল্ড এলিমেন্টগুলোকে মেজার এবং প্লেস করতে পারবেন। একটি লেআউট মেজার করা যায় শুধুমাত্র মেজারমেন্ট এবং লেআউট পাসের সময়, এবং একটি চাইল্ড এলিমেন্টকে প্লেস করা যায় শুধুমাত্র লেআউট পাসের সময় (এবং শুধুমাত্র মেজার করার পরেই)। MeasureScope এবং PlacementScope মতো Compose স্কোপগুলোর কারণে, এই নিয়মটি কম্পাইল টাইমেই কার্যকর করা হয়।

লেআউট মডিফায়ার ব্যবহার করুন

কোনো এলিমেন্ট কীভাবে পরিমাপ করা হবে এবং বিন্যস্ত করা হবে, তা পরিবর্তন করতে আপনি layout মডিফায়ার ব্যবহার করতে পারেন। Layout হলো একটি ল্যাম্বডা; এর প্যারামিটারগুলোর মধ্যে রয়েছে পরিমাপযোগ্য এলিমেন্ট, যা measurable হিসেবে পাস করা হয়, এবং সেই কম্পোজেবলের আগত সীমাবদ্ধতাগুলো, যা constraints ' হিসেবে পাস করা হয়। একটি কাস্টম লেআউট মডিফায়ার দেখতে এইরকম হতে পারে:

fun Modifier.customLayoutModifier() =
    layout { measurable, constraints ->
        // ...
    }

স্ক্রিনে একটি Text প্রদর্শন করুন এবং টেক্সটের প্রথম লাইনের শীর্ষ থেকে বেসলাইন পর্যন্ত দূরত্ব নিয়ন্ত্রণ করুন। paddingFromBaseline মডিফায়ারটি ঠিক এই কাজটিই করে; আপনি এখানে এটিকে একটি উদাহরণ হিসেবে প্রয়োগ করছেন। তা করার জন্য, layout মডিফায়ার ব্যবহার করে কম্পোজেবলটিকে স্ক্রিনে ম্যানুয়ালি স্থাপন করুন। এখানে ফলাফলস্বরূপ আচরণটি দেখানো হলো যেখানে Text টপ প্যাডিং 24.dp তে সেট করা হয়েছে:

এটি সাধারণ UI প্যাডিং, যা এলিমেন্টগুলোর মধ্যে ফাঁকা স্থান নির্ধারণ করে, এবং টেক্সট প্যাডিং, যা একটি বেসলাইন থেকে পরবর্তী বেসলাইন পর্যন্ত ফাঁকা স্থান নির্ধারণ করে, এদের মধ্যে পার্থক্য দেখায়।
চিত্র ২. paddingFromBaseline প্রয়োগ করা টেক্সট।

ওই ব্যবধানটি তৈরি করার কোডটি নিচে দেওয়া হলো:

fun Modifier.firstBaselineToTop(
    firstBaselineToTop: Dp
) = layout { measurable, constraints ->
    // Measure the composable
    val placeable = measurable.measure(constraints)

    // Check the composable has a first baseline
    check(placeable[FirstBaseline] != AlignmentLine.Unspecified)
    val firstBaseline = placeable[FirstBaseline]

    // Height of the composable with padding - first baseline
    val placeableY = firstBaselineToTop.roundToPx() - firstBaseline
    val height = placeable.height + placeableY
    layout(placeable.width, height) {
        // Where the composable gets placed
        placeable.placeRelative(0, placeableY)
    }
}

ঐ কোডটিতে যা ঘটছে তা হলো:

  1. measurable lambda প্যারামিটারে, আপনি measurable.measure(constraints) কল করার মাধ্যমে উক্ত প্যারামিটার দ্বারা উপস্থাপিত Text পরিমাপ করেন।
  2. আপনি layout(width, height) মেথডটি কল করে কম্পোজেবলটির আকার নির্দিষ্ট করেন, যা র‍্যাপ করা এলিমেন্টগুলো স্থাপন করার জন্য ব্যবহৃত একটি ল্যাম্বডাও প্রদান করে। এক্ষেত্রে, এটি হলো শেষ বেসলাইন এবং যুক্ত করা টপ প্যাডিংয়ের মধ্যবর্তী উচ্চতা।
  3. placeable.place(x, y) কল করে আপনি র‍্যাপ করা এলিমেন্টগুলোকে স্ক্রিনে স্থাপন করেন। যদি র‍্যাপ করা এলিমেন্টগুলো স্থাপন করা না হয়, তবে সেগুলো দেখা যাবে না। y অবস্থানটি টপ প্যাডিং-এর সাথে সঙ্গতিপূর্ণ: অর্থাৎ টেক্সটের প্রথম বেসলাইনের অবস্থান।

এটি প্রত্যাশিতভাবে কাজ করছে কিনা তা যাচাই করতে, একটি Text এই মডিফায়ারটি ব্যবহার করুন:

@Preview
@Composable
fun TextWithPaddingToBaselinePreview() {
    MyApplicationTheme {
        Text("Hi there!", Modifier.firstBaselineToTop(32.dp))
    }
}

@Preview
@Composable
fun TextWithNormalPaddingPreview() {
    MyApplicationTheme {
        Text("Hi there!", Modifier.padding(top = 32.dp))
    }
}

টেক্সট এলিমেন্টগুলোর একাধিক প্রিভিউ; একটিতে এলিমেন্টগুলোর মধ্যে সাধারণ প্যাডিং দেখানো হয়েছে, অন্যটিতে একটি বেসলাইন থেকে পরবর্তী বেসলাইন পর্যন্ত প্যাডিং দেখানো হয়েছে।
চিত্র ৩. একটি Text কম্পোজেবল-এ মডিফায়ার প্রয়োগ এবং তার প্রিভিউ।

কাস্টম লেআউট তৈরি করুন

layout মডিফায়ার শুধুমাত্র কলিং কম্পোজেবলটিকে পরিবর্তন করে। একাধিক কম্পোজেবলের পরিমাপ ও লেআউট করার জন্য, এর পরিবর্তে Layout কম্পোজেবল ব্যবহার করুন। এই কম্পোজেবলটি আপনাকে চাইল্ড এলিমেন্টগুলোর পরিমাপ ও লেআউট ম্যানুয়ালি করতে দেয়। Column এবং Row মতো সমস্ত উচ্চ-স্তরের লেআউট Layout কম্পোজেবল দিয়ে তৈরি করা হয়।

এই উদাহরণটি Column এর একটি অত্যন্ত প্রাথমিক সংস্করণ তৈরি করে। বেশিরভাগ কাস্টম লেআউট এই প্যাটার্নটি অনুসরণ করে:

@Composable
fun MyBasicColumn(
    modifier: Modifier = Modifier,
    content: @Composable () -> Unit
) {
    Layout(
        modifier = modifier,
        content = content
    ) { measurables, constraints ->
        // measure and position children given constraints logic here
        // ...
    }
}

layout মডিফায়ারের মতোই, measurables হলো পরিমাপযোগ্য চাইল্ডগুলোর তালিকা এবং constraints হলো প্যারেন্টের দেওয়া সীমাবদ্ধতাগুলো। আগের যুক্তি অনুসরণ করে, MyBasicColumn এইভাবে ইমপ্লিমেন্ট করা যেতে পারে:

@Composable
fun MyBasicColumn(
    modifier: Modifier = Modifier,
    content: @Composable () -> Unit
) {
    Layout(
        modifier = modifier,
        content = content
    ) { measurables, constraints ->
        // Don't constrain child views further, measure them with given constraints
        // List of measured children
        val placeables = measurables.map { measurable ->
            // Measure each children
            measurable.measure(constraints)
        }

        // Set the size of the layout as big as it can
        layout(constraints.maxWidth, constraints.maxHeight) {
            // Track the y co-ord we have placed children up to
            var yPosition = 0

            // Place children in the parent layout
            placeables.forEach { placeable ->
                // Position item on the screen
                placeable.placeRelative(x = 0, y = yPosition)

                // Record the y co-ord placed up to
                yPosition += placeable.height
            }
        }
    }
}

চাইল্ড কম্পোজেবলগুলো Layout কনস্ট্রেইন্ট ( minHeight কনস্ট্রেইন্ট ছাড়া) দ্বারা সীমাবদ্ধ থাকে এবং এগুলো পূর্ববর্তী কম্পোজেবলের yPosition এর উপর ভিত্তি করে স্থাপন করা হয়।

কাস্টম কম্পোজেবলটি যেভাবে ব্যবহার করা হবে তা নিচে দেওয়া হলো:

@Composable
fun CallingComposable(modifier: Modifier = Modifier) {
    MyBasicColumn(modifier.padding(8.dp)) {
        Text("MyBasicColumn")
        Text("places items")
        Text("vertically.")
        Text("We've done it by hand!")
    }
}

একটি কলামে একাধিক টেক্সট উপাদান একটির উপর আরেকটি করে সাজানো।
চিত্র ৪. কাস্টম Column বাস্তবায়ন।

বিন্যাস দিকনির্দেশনা

কম্পোজিশন লোকালের LocalLayoutDirection পরিবর্তন করে একটি কম্পোজেবলের লেআউটের দিক পরিবর্তন করুন।

আপনি যদি স্ক্রিনে ম্যানুয়ালি কম্পোজেবল স্থাপন করেন, তাহলে LayoutDirection টি layout মডিফায়ার বা Layout কম্পোজেবলের LayoutScope এর একটি অংশ হয়।

layoutDirection ব্যবহার করার সময়, place ব্যবহার করে কম্পোজেবল আইটেমগুলো রাখুন। placeRelative পদ্ধতির মতো নয়, place লেআউটের দিকের (বাম থেকে ডান বনাম ডান থেকে বাম) উপর ভিত্তি করে পরিবর্তিত হয় না।

কাস্টম লেআউটের বাস্তবায়ন

Compose-এর বেসিক লেআউট অংশে লেআউট এবং মডিফায়ার সম্পর্কে আরও জানুন, এবং কাস্টম লেআউট তৈরি করে এমন Compose স্যাম্পলগুলোতে কাস্টম লেআউটের বাস্তব প্রয়োগ দেখুন।

আরও জানুন

Compose-এ কাস্টম লেআউট সম্পর্কে আরও জানতে, নিম্নলিখিত অতিরিক্ত রিসোর্সগুলো দেখুন।

ভিডিও

{% হুবহু %} {% endverbatim %} {% হুবহু %} {% endverbatim %}