WindowInsetsRulers সম্পর্কে

WindowInsets হল Jetpack Compose-এর স্ট্যান্ডার্ড API যা স্ক্রিনের সেইসব অংশ ম্যানেজ করে যেগুলি সিস্টেম UI-এর মাধ্যমে আংশিক বা সম্পূর্ণভাবে অস্পষ্ট হয়ে যায়। এইসব জায়গার মধ্যে স্ট্যাটাস বার, নেভিগেশন বার ও স্ক্রিনের কীবোর্ড অন্তর্ভুক্ত। আপনি বিকল্প হিসেবে, সিস্টেম বার ও ডিসপ্লে কাট-আউটের সাথে আপনার কন্টেন্ট অ্যালাইন করতে SafeDrawing থেকে Modifier.fitInside বা Modifier.fitOutside-এর মতো আগে থেকে নির্ধারিত WindowInsetsRulers পাস করতে পারেন অথবা কাস্টম WindowInsetsRulers তৈরি করতে পারেন।

WindowInsetsRulers-এর সুবিধা

  • ব্যবহারের জটিলতা এড়ায়: এটি লেআউটের প্লেসমেন্ট ফেজ চলাকালীন কাজ করে। এর অর্থ হল, এটি ইনসেট কনজাম্পশন চেনকে সম্পূর্ণভাবে বাইপাস করে এবং পেরেন্ট লেআউট যাই করুক না কেন, সিস্টেম বার ও ডিসপ্লে কাটআউটের সঠিক, পরম অবস্থান সবসময় প্রদান করতে পারে। অ্যানসেস্টর কম্পোজেবল ভুলভাবে ইনসেট ব্যবহার করলে, Modifier.fitInside বা Modifier.fitOutside পদ্ধতি ব্যবহার করে সমস্যার সমাধান করা যায়।
  • সহজেই সিস্টেম বার এড়িয়ে যান: এটি আপনার অ্যাপ কন্টেন্টকে সিস্টেম বার ও ডিসপ্লে কাটআউট এড়িয়ে যেতে সাহায্য করে এবং সরাসরি WindowInsets ব্যবহার করার চেয়ে আরও সহজ হতে পারে।
  • অত্যন্ত কাস্টমাইজযোগ্য: ডেভেলপাররা কাস্টম রুলার অনুযায়ী কন্টেন্ট অ্যালাইন করতে পারেন এবং কাস্টম লেআউটের মাধ্যমে তাদের লেআউটের উপর সুনির্দিষ্ট নিয়ন্ত্রণ রাখতে পারেন।

WindowInsetsRulers-এর অসুবিধা

  • পরিমাপের জন্য ব্যবহার করা যাবে না: কারণ এটি প্লেসমেন্ট পর্যায়ে কাজ করে, তাই এটি যে পজিশন সংক্রান্ত তথ্য প্রদান করে তা আগের পরিমাপের পর্যায়ে উপলভ্য থাকে না।

Modifier পদ্ধতির সাথে আপনার কন্টেন্ট অ্যালাইন করুন

Modifier.fitInside অ্যাপকে সিস্টেম বার ও ডিসপ্লে কাটআউটের সাথে কন্টেন্ট অ্যালাইন করার অনুমতি দেয়। এটি WindowInsets-এর পরিবর্তে ব্যবহার করা যেতে পারে। Modifier.fitOutside সাধারণত Modifier.fitInside-এর বিপরীত।

যেমন, অ্যাপের কন্টেন্ট সিস্টেম বার ও ডিসপ্লে কাটআউট এড়িয়ে যাচ্ছে কিনা তা যাচাই করতে, আপনি fitInside(WindowInsetsRulers.safeDrawing.current) ব্যবহার করতে পারেন।

@Composable
fun FitInsideDemo(modifier: Modifier) {
    Box(
        modifier = modifier
            .fillMaxSize()
            // Or DisplayCutout, Ime, NavigationBars, StatusBar, etc...
            .fitInside(WindowInsetsRulers.SafeDrawing.current)
    )
}

নিচের সারণিতে দেখানো হয়েছে যে Modifier.fitInside বা Modifier.fitOutside-এর সাথে আগে থেকে নির্ধারিত রুলার ব্যবহার করলে আপনার অ্যাপের কন্টেন্ট কেমন দেখাবে।

পূর্বনির্ধারিত রুলারের ধরন

Modifier.fitInside

Modifier.fitOutside

DisplayCutout

Ime

N/A

NavigationBars

SafeDrawing

প্রযোজ্য নয় (পরিবর্তে StatusBar, CaptionBar, NavigationBar ব্যবহার করুন)

StatusBar

Modifier.fitInside এবং Modifier.fitOutside ব্যবহার করার জন্য কম্পোজেবলকে সীমাবদ্ধ করতে হবে। এর অর্থ হল, আপনাকে Modifier.size বা Modifier.fillMaxSize-এর মতো মডিফায়ার উল্লেখ করতে হবে।

SafeDrawing-এ Modifier.fitOutside এবং SystemBars-এর মতো কিছু রুলার একাধিক রুলার রিটার্ন করে। এই ক্ষেত্রে, Android একটি রুলার ব্যবহার করে Composable-কে বাঁ, উপর, ডান, নিচ থেকে প্লেস করে।

Modifier.fitInside-এর মাধ্যমে IME এড়িয়ে চলুন

Modifier.fitInside সহ IME-এর মাধ্যমে নিচের এলিমেন্ট ম্যানেজ করতে, RectRuler-এ পাস করুন যা NavigationBar ও Ime-এর সবচেয়ে ভিতরের ভ্যালু নেয়।

@Composable
fun FitInsideWithImeDemo(modifier: Modifier) {
    Box(
        modifier = modifier
            .fillMaxSize()
            .fitInside(
                RectRulers.innermostOf(
                    WindowInsetsRulers.NavigationBars.current,
                    WindowInsetsRulers.Ime.current
                )
            )
    ) {
        TextField(
            value = "Demo IME Insets",
            onValueChange = {},
            modifier = modifier.align(Alignment.BottomStart).fillMaxWidth()
        )
    }
}

Modifier.fitInside-এর মাধ্যমে স্ট্যাটাস বার ও ক্যাপশন বার এড়িয়ে যান

একইভাবে, উপরের এলিমেন্ট যাচাই করতে, স্ট্যাটাস বার ও ক্যাপশন বার এড়িয়ে যান, Modifier.fitInside-এর সাথে, RectRuler পাস করুন যা StatusBars ও CaptionBar-এর সবচেয়ে ভিতরের ভ্যালু নেয়।

@Composable
fun FitInsideWithStatusAndCaptionBarDemo(modifier: Modifier) {
    Box(
        modifier = modifier
            .fillMaxSize()
            .fitInside(
                RectRulers.innermostOf(
                    WindowInsetsRulers.StatusBars.current,
                    WindowInsetsRulers.CaptionBar.current
                )
            )
    )
}

কাস্টম WindowInsetsRulers তৈরি করুন

আপনি কাস্টম রুলারে কন্টেন্ট অ্যালাইন করতে পারবেন। যেমন, এমন একটি ব্যবহারের ক্ষেত্রে বিবেচনা করুন যেখানে একটি পেরেন্ট কম্পোজেবল ইনসেটগুলি ভুলভাবে পরিচালনা করে যার ফলে ডাউনস্ট্রিম চাইল্ডে প্যাডিং সমস্যা হয়। যদিও এই সমস্যাটি Modifier.fitInside ব্যবহার করা সহ অন্যান্য উপায়ে সমাধান করা যেতে পারে, আপনি নিম্নলিখিত উদাহরণ এবং ভিডিওতে দেখানো হিসাবে প্যারেন্ট আপস্ট্রিমে সমস্যাটি সমাধান না করেই চাইল্ড কম্পোজেবলকে সঠিকভাবে সারিবদ্ধ করতে একটি কাস্টম রুলার তৈরি করতে পারেন:

@Composable
fun WindowInsetsRulersDemo(modifier: Modifier) {
    Box(
        contentAlignment = BottomCenter,
        modifier = modifier
            .fillMaxSize()
            // The mistake that causes issues downstream, as .padding doesn't consume insets.
            // While it's correct to instead use .windowInsetsPadding(WindowInsets.navigationBars),
            // assume it's difficult to identify this issue to see how WindowInsetsRulers can help.
            .padding(WindowInsets.navigationBars.asPaddingValues())
    ) {
        TextField(
            value = "Demo IME Insets",
            onValueChange = {},
            modifier = modifier
                // Use alignToSafeDrawing() instead of .imePadding() to precisely place this child
                // Composable without having to fix the parent upstream.
                .alignToSafeDrawing()

            // .imePadding()
            // .fillMaxWidth()
        )
    }
}

fun Modifier.alignToSafeDrawing(): Modifier {
    return layout { measurable, constraints ->
        if (constraints.hasBoundedWidth && constraints.hasBoundedHeight) {
            val placeable = measurable.measure(constraints)
            val width = placeable.width
            val height = placeable.height
            layout(width, height) {
                val bottom = WindowInsetsRulers.SafeDrawing.current.bottom
                    .current(0f).roundToInt() - height
                val right = WindowInsetsRulers.SafeDrawing.current.right
                    .current(0f).roundToInt()
                val left = WindowInsetsRulers.SafeDrawing.current.left
                    .current(0f).roundToInt()
                measurable.measure(Constraints.fixed(right - left, height))
                    .place(left, bottom)
            }
        } else {
            val placeable = measurable.measure(constraints)
            layout(placeable.width, placeable.height) {
                placeable.place(0, 0)
            }
        }
    }
}

নিচের ভিডিওতে বাঁদিকের ছবিতে আপস্ট্রিম পেরেন্টের কারণে হওয়া সমস্যাজনক IME ইনসেট কনজাম্পশনের উদাহরণ দেখানো হয়েছে এবং ডানদিকের ছবিতে কাস্টম রুলার ব্যবহার করে সমস্যার সমাধান করা হয়েছে। TextField-এর নিচে অতিরিক্ত প্যাডিং দেখানো হয়েছে নেভিগেশন বার প্যাডিং পেরেন্ট দ্বারা ব্যবহৃত না হওয়ার কারণে কম্পোজেবল। আগের কোড স্যাম্পেলে যেমন দেখানো হয়েছে, কাস্টম রুলার ব্যবহার করে ডানদিকের ছবিতে বাচ্চাকে সঠিক লোকেশনে প্লেস করা হয়েছে।

অভিভাবক সীমাবদ্ধ কিনা তা যাচাই করুন

WindowInsetsRulers নিরাপদে ব্যবহার করার জন্য, অভিভাবক যেন সঠিক বিধিনিষেধ প্রদান করেন তা নিশ্চিত করুন। মূল কন্টেনারের সাইজ নির্দিষ্ট হতে হবে এবং WindowInsetsRulers ব্যবহার করে এমন চাইল্ড কন্টেনারের সাইজের উপর নির্ভর করলে চলবে না। প্যারেন্ট কম্পোজেবলে fillMaxSize বা অন্য সাইজ মডিফায়ার ব্যবহার করুন।

একইভাবে, verticalScroll-এর মতো স্ক্রলিং কন্টেনারের মধ্যে WindowInsetsRulers ব্যবহার করে এমন কম্পোজেবল রাখলে অপ্রত্যাশিত আচরণ হতে পারে কারণ স্ক্রলিং কন্টেনার সীমাহীন উচ্চতার সীমাবদ্ধতা প্রদান করে, যা রুলারের লজিকের সাথে বেমানান।