Compose-এ Flow লেআউট

FlowRow ও FlowColumn হল কম্পোজ করার উপযুক্ত আইটেম যা Row ও Column-এর মতো, তবে পার্থক্য হল যে কন্টেনারে জায়গা না থাকলে আইটেম পরের লাইনে চলে যায়। এর ফলে একাধিক সারি বা কলাম তৈরি হয়। maxItemsInEachRow বা maxItemsInEachColumn সেট করার মাধ্যমে একটি লাইনে আইটেমের সংখ্যাও কন্ট্রোল করা যেতে পারে। রেসপন্সিভ লেআউট তৈরি করতে আপনি প্রায়ই FlowRow ও FlowColumn ব্যবহার করতে পারেন— কোনও আইটেম এক ডাইমেনশনের জন্য খুব বড় হলে কন্টেন্ট কাট-অফ হবে না এবং maxItemsInEach*-এর সাথে Modifier.weight(weight)-এর কম্বিনেশন ব্যবহার করলে এমন লেআউট তৈরি করতে সাহায্য করতে পারে যা প্রয়োজন হলে কোনও সারি বা কলামের প্রস্থ পূরণ/সম্প্রসারিত করে।

এর সাধারণ উদাহরণ হল চিপ বা ফিল্টারিং UI:

FlowRow-তে ৫টি চিপ, আর কোনও জায়গা না থাকলে ওভারফ্লো হয়ে পরের লাইনে চলে যায়।
ছবি ১. FlowRow
-এর উদাহরণ

প্রাথমিক ব্যবহার

FlowRow বা FlowColumn ব্যবহার করতে, এই কম্পোজ করার উপযুক্ত আইটেম তৈরি করুন এবং এর মধ্যে সেইসব আইটেম রাখুন যেগুলি স্ট্যান্ডার্ড ফ্লো অনুসরণ করবে:

@Composable
private fun FlowRowSimpleUsageExample() {
    FlowRow(modifier = Modifier.padding(8.dp)) {
        ChipItem("Price: High to Low")
        ChipItem("Avg rating: 4+")
        ChipItem("Free breakfast")
        ChipItem("Free cancellation")
        ChipItem("£50 pn")
    }
}

এই স্নিপেটটি উপরের UI-এর মতো ফলাফল দেয়, যেখানে প্রথম সারিতে আর জায়গা না থাকলে আইটেমগুলি অটোমেটিক পরের সারিতে চলে যায়।

ফ্লো লেআউটের ফিচার

Flow লেআউটে নিম্নলিখিত ফিচার ও প্রপার্টি আছে যা আপনি নিজের অ্যাপে বিভিন্ন লেআউট তৈরি করতে ব্যবহার করতে পারবেন।

প্রধান অক্ষের সজ্জা: অনুভূমিক বা উল্লম্ব সজ্জা

প্রধান অ্যাক্সিস হল সেই অ্যাক্সিস যার উপরে আইটেমগুলি সাজানো হয় (যেমন, FlowRow-এ, আইটেমগুলি অনুভূমিকভাবে সাজানো হয়)। FlowRow-এর মধ্যে থাকা horizontalArrangement প্যারামিটার আইটেমগুলির মধ্যে ফাঁকা জায়গা কীভাবে ডিস্ট্রিবিউট করা হয় তা নিয়ন্ত্রণ করে।

FlowRow-এর জন্য আইটেমে horizontalArrangement সেট করার উদাহরণ নিচের সারণীতে দেওয়া হল:

FlowRow-এ অনুভূমিক সজ্জা সেট করা হয়েছে

ফলাফল

Arrangement.Start (Default)

'স্টার্ট' দিয়ে সাজানো আইটেম

Arrangement.SpaceBetween

দুটি আইটেমের মধ্যে স্পেস রেখে আইটেম সাজানো

Arrangement.Center

মাঝখানে সাজানো আইটেম

Arrangement.End

শেষের দিকে সাজানো আইটেম

Arrangement.SpaceAround

আইটেমগুলি এমনভাবে সাজানো হয়েছে যে সেগুলির চারপাশে জায়গা রয়েছে

Arrangement.spacedBy(8.dp)

নির্দিষ্ট dp-এর মাধ্যমে স্পেস করা আইটেম

FlowColumn-এর জন্য, verticalArrangement-এর সাথে একই ধরনের বিকল্প উপলভ্য, যার ডিফল্ট মান হল Arrangement.Top।

ক্রস অ্যাক্সিস অ্যারেঞ্জমেন্ট

ক্রস অ্যাক্সিস হল মূল অ্যাক্সিসের বিপরীত দিকের অ্যাক্সিস। যেমন, FlowRow-এ এটি হল উল্লম্ব অক্ষ। কন্টেনারের মধ্যে থাকা সামগ্রিক কন্টেন্ট ক্রস অ্যাক্সিসে কীভাবে সাজানো হবে তা পরিবর্তন করতে, FlowRow-এর জন্য verticalArrangement এবং FlowColumn-এর জন্য horizontalArrangement ব্যবহার করুন।

FlowRow-এর জন্য, আইটেমে আলাদা verticalArrangement সেট করার উদাহরণ নিচে দেওয়া হল:

FlowRow-এ উল্লম্ব সজ্জা সেট করা হয়েছে

ফলাফল

Arrangement.Top (Default)

কন্টেনারের উপরের অংশের ব্যবস্থা

Arrangement.Bottom

কন্টেনারের নিচের দিকের ব্যবস্থা

Arrangement.Center

কন্টেনার সেন্টার অ্যারেঞ্জমেন্ট

FlowColumn-এর জন্য, horizontalArrangement-এর সাথে একই ধরনের বিকল্প উপলভ্য। ডিফল্ট ক্রস অ্যাক্সিস অ্যারেঞ্জমেন্ট হল Arrangement.Start।

আলাদা আলাদা আইটেম অ্যালাইন করা

আপনি হয়ত সারির মধ্যে আলাদা আলাদা আইটেমকে আলাদা অ্যালাইনমেন্টে পজিশন করতে চাইবেন। এটি verticalArrangement ও horizontalArrangement-এর থেকে আলাদা কারণ এটি বর্তমান লাইনের মধ্যে আইটেম অ্যালাইন করে। আপনি Modifier.align()-এর মাধ্যমে এটি প্রয়োগ করতে পারবেন।

যেমন, FlowRow-এর আইটেমগুলি আলাদা আলাদা উচ্চতার হলে, সারিটি সবচেয়ে বড় আইটেমের উচ্চতা নেয় এবং আইটেমগুলিতে Modifier.align(alignmentOption) প্রয়োগ করে:

FlowRow-এ উল্লম্ব সারিবদ্ধতা সেট করা হয়েছে

ফলাফল

Alignment.Top (Default)

আইটেম উপরে অ্যালাইন করা আছে

Alignment.Bottom

নিচের দিকে অ্যালাইন করা আইটেম

Alignment.CenterVertically

আইটেমগুলি কেন্দ্রে অ্যালাইন করা হয়েছে

FlowColumn-এর জন্য, একই ধরনের বিকল্প উপলভ্য। ডিফল্ট অ্যালাইনমেন্ট হল Alignment.Start।

সারি বা কলামে সর্বাধিক আইটেম

maxItemsInEachRow বা maxItemsInEachColumn প্যারামিটারগুলি, পরবর্তী লাইনে র‍্যাপ করার আগে একটি লাইনে সর্বাধিক আইটেমকে অনুমতি দেওয়ার জন্য মূল অক্ষকে সংজ্ঞায়িত করে। ডিফল্ট হল Int.MAX_INT, যা যতগুলি সম্ভব আইটেমকে অনুমতি দেয়, যতক্ষণ না সেগুলির সাইজ লাইনটিতে ফিট করার অনুমতি দেয়।

যেমন, maxItemsInEachRow সেট করলে, প্রাথমিক লেআউটে শুধুমাত্র ৩টি আইটেম রাখতে হবে:

সর্বাধিক সেট করা নেই

maxItemsInEachRow = 3

ফ্লো সারিতে কোনও সর্বাধিক সংখ্যা সেট করা নেই ফ্লো রোতে সেট করা সর্বাধিক আইটেম

আইটেমের ওজন

কোনও আইটেমের ফ্যাক্টর এবং এটি যে লাইনে প্লেস করা হয়েছে সেটির উপলভ্য স্পেসের উপর ভিত্তি করে সেটির ওজন বৃদ্ধি পায়। গুরুত্বপূর্ণভাবে, FlowRow এবং Row এর মধ্যে পার্থক্য হল, আইটেমের প্রস্থ গণনা করার জন্য কীভাবে ওজন ব্যবহার করা হয়। Rows-এর জন্য, ওজন Row-এর সব আইটেমের উপর ভিত্তি করে হিসেব করা হয়। FlowRow-এর ক্ষেত্রে, ওজন কোনও আইটেম যে লাইনে প্লেস করা হয়েছে সেটির আইটেমের উপর ভিত্তি করে নির্ধারণ করা হয়, FlowRow কন্টেনারের সব আইটেমের উপর ভিত্তি করে নয়।

যেমন, আপনার কাছে ৪টি আইটেম আছে যেগুলি একটি লাইনে আছে এবং প্রত্যেকটির আলাদা আলাদা ওজন হল 1f, 2f, 1f ও 3f, তাহলে মোট ওজন হল 7f। একটি সারি বা কলামে বাকি থাকা স্পেসকে 7f দিয়ে ভাগ করা হবে। তারপর, প্রতিটি আইটেমের প্রস্থ এগুলি ব্যবহার করে হিসেব করা হবে: weight * (remainingSpace / totalWeight).

গ্রিড-লাইক লেআউট তৈরি করতে, আপনি FlowRow বা FlowColumn-এর সাথে Modifier.weight এবং সর্বাধিক আইটেমের কম্বিনেশন ব্যবহার করতে পারেন। এই পদ্ধতিটি আপনার ডিভাইসের সাইজ অনুযায়ী অ্যাডজাস্ট করা যায় এমন রেসপন্সিভ লেআউট তৈরি করার জন্য উপযোগী।

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

ফ্লো রো সহ গ্রিড তৈরি করা হয়েছে
ছবি ২. FlowRow ব্যবহার করে গ্রিড তৈরি করা

সমান সাইজের আইটেমের গ্রিড তৈরি করতে, আপনি নিম্নলিখিত কাজগুলি করতে পারেন:

val rows = 3
val columns = 3
FlowRow(
    modifier = Modifier.padding(4.dp),
    horizontalArrangement = Arrangement.spacedBy(4.dp),
    maxItemsInEachRow = rows
) {
    val itemModifier = Modifier
        .padding(4.dp)
        .height(80.dp)
        .weight(1f)
        .clip(RoundedCornerShape(8.dp))
        .background(MaterialColors.Blue200)
    repeat(rows * columns) {
        Spacer(modifier = itemModifier)
    }
}

গুরুত্বপূর্ণভাবে, আপনি যদি অন্য একটি আইটেম যোগ করেন এবং এটিকে ৯ বারের পরিবর্তে ১০ বার পুনরাবৃত্তি করেন, তাহলে শেষ আইটেমটি সম্পূর্ণ শেষ কলামটি দখল করে নেয়, কারণ পুরো সারির মোট ওজন 1f:

গ্রিডে শেষ আইটেম সম্পূর্ণ সাইজে
ছবি ৩. FlowRow ব্যবহার করে এমন একটি গ্রিড তৈরি করা যেখানে শেষ আইটেমটি সম্পূর্ণ প্রস্থ জুড়ে থাকে

আপনি অন্যান্য Modifiers যেমন Modifier.width(exactDpAmount), Modifier.aspectRatio(aspectRatio) বা Modifier.fillMaxWidth(fraction)-এর সাথে ওয়েট মিলিয়ে নিতে পারেন। এইসব মডিফায়ার একসাথে কাজ করে FlowRow (বা FlowColumn)-এর মধ্যে আইটেমের রেসপন্সিভ সাইজিংয়ের অনুমতি দেয়।

এছাড়াও, আপনি বিভিন্ন আইটেমের সাইজের একটি বিকল্প গ্রিড তৈরি করতে পারেন, যেখানে দুটি আইটেম প্রত্যেকটি অর্ধেক প্রস্থ নেয় এবং একটি আইটেম পরবর্তী কলামের সম্পূর্ণ প্রস্থ নেয়:

ফ্লো রো সহ অল্টারনেটিং গ্রিড
ছবি ৪. FlowRow সহ সারির বিকল্প সাইজ

আপনি নিম্নলিখিত কোডের মাধ্যমে এটি করতে পারবেন:

FlowRow(
    modifier = Modifier.padding(4.dp),
    horizontalArrangement = Arrangement.spacedBy(4.dp),
    maxItemsInEachRow = 2
) {
    val itemModifier = Modifier
        .padding(4.dp)
        .height(80.dp)
        .clip(RoundedCornerShape(8.dp))
        .background(Color.Blue)
    repeat(6) { item ->
        // if the item is the third item, don't use weight modifier, but rather fillMaxWidth
        if ((item + 1) % 3 == 0) {
            Spacer(modifier = itemModifier.fillMaxWidth())
        } else {
            Spacer(modifier = itemModifier.weight(0.5f))
        }
    }
}

ফ্র্যাকশনাল সাইজিং

Modifier.fillMaxWidth(fraction) ব্যবহার করে, কোনও আইটেমকে যে কন্টেনারটি নিতে হবে তার সাইজ নির্দিষ্ট করতে পারবেন। Row বা Column-এ প্রয়োগ করা হলে Modifier.fillMaxWidth(fraction) যেভাবে কাজ করে, এটি তার থেকে আলাদা, কারণ Row/Column আইটেমগুলি সম্পূর্ণ কন্টেনারের প্রস্থের পরিবর্তে অবশিষ্ট প্রস্থের একটি শতাংশ নেয়।

যেমন, নিম্নলিখিত কোডটি FlowRow vs Row ব্যবহার করার সময় আলাদা আলাদা ফলাফল তৈরি করে:

FlowRow(
    modifier = Modifier.padding(4.dp),
    horizontalArrangement = Arrangement.spacedBy(4.dp),
    maxItemsInEachRow = 3
) {
    val itemModifier = Modifier
        .clip(RoundedCornerShape(8.dp))
    Box(
        modifier = itemModifier
            .height(200.dp)
            .width(60.dp)
            .background(Color.Red)
    )
    Box(
        modifier = itemModifier
            .height(200.dp)
            .fillMaxWidth(0.7f)
            .background(Color.Blue)
    )
    Box(
        modifier = itemModifier
            .height(200.dp)
            .weight(1f)
            .background(Color.Magenta)
    )
}

FlowRow: মাঝের আইটেমটি সম্পূর্ণ কন্টেনার উইথের ০.৭ ফ্র্যাকশন।

ফ্লো রো সহ ফ্র্যাকশনাল প্রস্থ

Row: মাঝের আইটেমটি বাকি থাকা Row প্রস্থের ০.৭ শতাংশ জায়গা নিচ্ছে।

সারি সহ ভগ্নাংশ প্রস্থ

fillMaxColumnWidth() ও fillMaxRowHeight()

FlowColumn বা FlowRow-এর মধ্যে থাকা কোনও আইটেমে Modifier.fillMaxColumnWidth() বা Modifier.fillMaxRowHeight() প্রয়োগ করলে একই কলাম বা সারিতে থাকা আইটেমগুলি কলাম/সারির সবচেয়ে বড় আইটেমের সমান প্রস্থ বা উচ্চতা নেয়।

যেমন, এই উদাহরণে Android ডেজার্টের তালিকা দেখানোর জন্য FlowColumn ব্যবহার করা হয়েছে। আপনি প্রতিটি আইটেমের প্রস্থের পার্থক্য দেখতে পাবেন যখন Modifier.fillMaxColumnWidth() আইটেমে প্রয়োগ করা হয় বনাম যখন এটি প্রয়োগ করা হয় না এবং আইটেমগুলি র‍্যাপ হয়।

FlowColumn(
    Modifier
        .padding(20.dp)
        .fillMaxHeight()
        .fillMaxWidth(),
    horizontalArrangement = Arrangement.spacedBy(8.dp),
    verticalArrangement = Arrangement.spacedBy(8.dp),
    maxItemsInEachColumn = 5,
) {
    repeat(listDesserts.size) {
        Box(
            Modifier
                .fillMaxColumnWidth()
                .border(1.dp, Color.DarkGray, RoundedCornerShape(8.dp))
                .padding(8.dp)
        ) {

            Text(
                text = listDesserts[it],
                fontSize = 18.sp,
                modifier = Modifier.padding(3.dp)
            )
        }
    }
}

প্রতিটি আইটেমে Modifier.fillMaxColumnWidth() প্রয়োগ করা হয়েছে

fillMaxColumnWidth

প্রস্থে কোনও পরিবর্তন সেট করা নেই (র‍্যাপিং আইটেম)

সর্বাধিক কলামের প্রস্থ সেট করা নেই