Compose-এ ConstraintLayout

ConstraintLayout হল এমন একটি লেআউট যা আপনাকে স্ক্রিনে অন্যান্য কম্পোজেবলের সাপেক্ষে কম্পোজেবল প্লেস করতে দেয়। এটি একাধিক নেস্টেড Row, Column, Box এবং অন্যান্য কাস্টম লেআউট এলিমেন্ট ব্যবহার করার বিকল্প।

ভিউ সিস্টেমে, বড় ও জটিল লেআউট তৈরি করার জন্য ConstraintLayout ব্যবহার করার সাজেশন দেওয়া হয়, কারণ নেস্টেড ভিউয়ের তুলনায় ফ্ল্যাট ভিউ হায়ারার্কি পারফর্ম্যান্সের জন্য আরও ভালো। তবে, Compose-এর ক্ষেত্রে এটি কোনও সমস্যা নয়, কারণ এটি দক্ষতার সাথে গভীর লেআউট হায়ারার্কি ম্যানেজ করতে পারে, তাই ConstraintLayout ততটা উপকারী নয়।

ConstraintLayout দিয়ে শুরু করুন

Compose-এ ConstraintLayout ব্যবহার করতে, আপনাকে এই ডিপেন্ডেন্সি আপনার build.gradle-এ যোগ করতে হবে (Compose সেট-আপ ছাড়াও):

implementation "androidx.constraintlayout:constraintlayout-compose:$constraintlayout_compose_version"

Compose-এ ConstraintLayout নিম্নলিখিত উপায়ে DSL ব্যবহার করে কাজ করে:

  • ConstraintLayout-এ প্রতিটি কম্পোজেবলের জন্য রেফারেন্স তৈরি করুন, createRefs() বা createRefFor() ব্যবহার করে।
  • constrainAs() মডিফায়ার ব্যবহার করে কনস্ট্রেন্ট প্রদান করা হয়, যা রেফারেন্সকে প্যারামিটার হিসেবে গ্রহণ করে এবং বডি ল্যাম্বডাতে আপনাকে এর কনস্ট্রেন্ট নির্দিষ্ট করতে দেয়।
  • linkTo() বা অন্যান্য সহায়ক পদ্ধতি ব্যবহার করে সীমাবদ্ধতা নির্দিষ্ট করা হয়।
  • parent হল আগে থেকে থাকা রেফারেন্স যা ConstraintLayout কম্পোজ করার উপযুক্ত আইটেমের ক্ষেত্রে সীমাবদ্ধতা নির্দিষ্ট করতে ব্যবহার করা যেতে পারে।

ConstraintLayout ব্যবহার করে কম্পোজেবলের একটি উদাহরণ এখানে দেওয়া হল:

@Composable
fun ConstraintLayoutContent() {
    ConstraintLayout {
        // Create references for the composables to constrain
        val (button, text) = createRefs()

        Button(
            onClick = { /* Do something */ },
            // Assign reference "button" to the Button composable
            // and constrain it to the top of the ConstraintLayout
            modifier = Modifier.constrainAs(button) {
                top.linkTo(parent.top, margin = 16.dp)
            }
        ) {
            Text("Button")
        }

        // Assign reference "text" to the Text composable
        // and constrain it to the bottom of the Button composable
        Text(
            "Text",
            Modifier.constrainAs(text) {
                top.linkTo(button.bottom, margin = 16.dp)
            }
        )
    }
}

এই কোডটি Button-এর উপরের অংশকে 16.dp মার্জিন সহ পেরেন্টের সাথে এবং Text-কে Button-এর নিচের অংশের সাথে 16.dp মার্জিন সহ সীমাবদ্ধ করে।

টেক্সটের উপরে বোতামটি দেখা যায়
ছবি ১. ConstraintLayout-এ একটি Button এবং একটি Text কম্পোজেবল একে অপরের সাথে সীমাবদ্ধ।

ডিকাপল্ড API

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

এই ধরনের ক্ষেত্রে, আপনি অন্যভাবে ConstraintLayout ব্যবহার করতে পারেন:

  1. ConstraintLayout-এ প্যারামিটার হিসেবে ConstraintSet পাস করুন।
  2. ConstraintSet-এ তৈরি করা রেফারেন্সগুলি layoutId মডিফায়ার ব্যবহার করে কম্পোজেবলগুলিতে অ্যাসাইন করুন।

@Composable
fun DecoupledConstraintLayout() {
    BoxWithConstraints {
        val constraints = if (minWidth < 600.dp) {
            decoupledConstraints(margin = 16.dp) // Portrait constraints
        } else {
            decoupledConstraints(margin = 32.dp) // Landscape constraints
        }

        ConstraintLayout(constraints) {
            Button(
                onClick = { /* Do something */ },
                modifier = Modifier.layoutId("button")
            ) {
                Text("Button")
            }

            Text("Text", Modifier.layoutId("text"))
        }
    }
}

private fun decoupledConstraints(margin: Dp): ConstraintSet {
    return ConstraintSet {
        val button = createRefFor("button")
        val text = createRefFor("text")

        constrain(button) {
            top.linkTo(parent.top, margin = margin)
        }
        constrain(text) {
            top.linkTo(button.bottom, margin)
        }
    }
}

তারপর, আপনাকে যখন সীমাবদ্ধতা পরিবর্তন করতে হবে, তখন আপনি শুধু অন্য একটি ConstraintSet পাস করতে পারবেন।

ConstraintLayoutটি ধারণা

ConstraintLayout-এ নির্দেশিকা, বাধা ও চেনের মতো ধারণা রয়েছে যা আপনার কম্পোজেবলের মধ্যে এলিমেন্ট পজিশন করতে সাহায্য করতে পারে।

নির্দেশিকা

নির্দেশিকা হল লেআউট ডিজাইন করার জন্য ছোট ভিজ্যুয়াল সহায়ক। কম্পোজেবলকে একটি নির্দেশিকায় সীমাবদ্ধ করা যেতে পারে। পেরেন্ট কম্পোজেবলের মধ্যে নির্দিষ্ট dp বা percentage-এ এলিমেন্ট পজিশন করার জন্য গাইডলাইন উপযোগী।

দুই ধরনের নির্দেশিকা আছে, ভার্টিক্যাল ও হরাইজন্টাল। দুটি অনুভূমিক রেখা হল top ও bottom এবং দুটি উল্লম্ব রেখা হল start ও end।

ConstraintLayout {
    // Create guideline from the start of the parent at 10% the width of the Composable
    val startGuideline = createGuidelineFromStart(0.1f)
    // Create guideline from the end of the parent at 10% the width of the Composable
    val endGuideline = createGuidelineFromEnd(0.1f)
    //  Create guideline from 16 dp from the top of the parent
    val topGuideline = createGuidelineFromTop(16.dp)
    //  Create guideline from 16 dp from the bottom of the parent
    val bottomGuideline = createGuidelineFromBottom(16.dp)
}

নির্দেশিকা তৈরি করতে, প্রয়োজনীয় নির্দেশিকার ধরন সহ createGuidelineFrom* ব্যবহার করুন। এটি একটি রেফারেন্স তৈরি করে যা Modifier.constrainAs() ব্লকে ব্যবহার করা যেতে পারে।

ব্যারিয়ার

Barriers একাধিক কম্পোজেবলকে রেফারেন্স করে যাতে নির্দিষ্ট সাইডে সবচেয়ে এক্সট্রিম উইজেটের উপর ভিত্তি করে ভার্চুয়াল গাইডলাইন তৈরি করা যায়।

ব্যারিয়ার তৈরি করতে, createTopBarrier() (অথবা: createBottomBarrier(), createEndBarrier(), createStartBarrier()) ব্যবহার করুন এবং ব্যারিয়ার তৈরি করার জন্য প্রয়োজনীয় রেফারেন্স প্রদান করুন।

ConstraintLayout {
    val constraintSet = ConstraintSet {
        val button = createRefFor("button")
        val text = createRefFor("text")

        val topBarrier = createTopBarrier(button, text)
    }
}

তারপর Modifier.constrainAs() ব্লকে ব্যারিয়ার ব্যবহার করা যাবে।

চেন

চেন একটি একক অক্ষে (অনুভূমিকভাবে বা উল্লম্বভাবে) গ্রুপ-এর মতো আচরণ প্রদান করে। অন্য অক্ষটি স্বাধীনভাবে সীমাবদ্ধ করা যেতে পারে।

চেন তৈরি করতে, createVerticalChain অথবা createHorizontalChain ব্যবহার করুন:

ConstraintLayout {
    val constraintSet = ConstraintSet {
        val button = createRefFor("button")
        val text = createRefFor("text")

        val verticalChain = createVerticalChain(button, text, chainStyle = ChainStyle.Spread)
        val horizontalChain = createHorizontalChain(button, text)
    }
}

তারপর চেইনটি Modifier.constrainAs() ব্লকে ব্যবহার করা যেতে পারে।

একটি চেইন বিভিন্ন ChainStyles দিয়ে কনফিগার করা যেতে পারে, যা সিদ্ধান্ত নেয় কীভাবে কম্পোজেবলের আশেপাশের স্পেসের সাথে ডিল করতে হবে, যেমন:

  • ChainStyle.Spread: প্রথম কম্পোজেবলের আগে এবং শেষ কম্পোজেবলের পরে খালি জায়গা সহ, সব কম্পোজেবল জুড়ে সমানভাবে স্পেস ডিস্ট্রিবিউট করা হয়।
  • ChainStyle.SpreadInside: প্রথম কম্পোজেবলের আগে বা শেষ কম্পোজেবলের পরে কোনও ফাঁকা জায়গা না রেখে, সমস্ত কম্পোজেবল জুড়ে সমানভাবে জায়গা বিতরণ করা হয়।
  • ChainStyle.Packed: প্রথম কম্পোজেবলের আগে এবং শেষ কম্পোজেবলের পরে স্পেস ডিস্ট্রিবিউট করা হয়, কম্পোজেবলগুলি একে অপরের মধ্যে স্পেস ছাড়াই একসাথে প্যাক করা হয়।