WindowInsetsRulers के बारे में जानकारी

WindowInsets Jetpack Compose में, स्टैंडर्ड एपीआई है. इसका इस्तेमाल, स्क्रीन के उन हिस्सों को मैनेज करने के लिए किया जाता है जो सिस्टम यूज़र इंटरफ़ेस (यूआई) की वजह से, पूरी तरह या आंशिक तौर पर दिख नहीं पाते. इन हिस्सों में स्टेटस बार, नेविगेशन बार, और ऑन-स्क्रीन कीबोर्ड शामिल हैं. इसके अलावा, पहले से तय WindowInsetsRulers को Modifier.fitInside या Modifier.fitOutside में पास किया जा सकता है. जैसे, SafeDrawing. इससे, आपके कॉन्टेंट को सिस्टम बार और डिसप्ले कटआउट के साथ अलाइन किया जा सकता है. साथ ही, पसंद के मुताबिक WindowInsetsRulers भी बनाए जा सकते हैं.

WindowInsetsRulers के फ़ायदे

  • कॉन्टेंट को दिखाने में होने वाली मुश्किलों से बचाता है: यह लेआउट के प्लेसमेंट फ़ेज़ के दौरान काम करता है. इसका मतलब है कि यह इनसेट के इस्तेमाल की चेन को पूरी तरह से बाईपास कर सकता है. साथ ही, सिस्टम बार और डिसप्ले कटआउट की सही और सटीक पोज़िशन हमेशा उपलब्ध करा सकता है. भले ही, पैरंट लेआउट ने कुछ भी किया हो. Modifier.fitInside या Modifier.fitOutside तरीकों का इस्तेमाल करने से, उन समस्याओं को ठीक करने में मदद मिलती है जब पूर्वज कंपोज़ेबल, इनसेट का गलत तरीके से इस्तेमाल करते हैं.
  • सिस्टम बार से आसानी से बचा जा सकता है: इससे आपके ऐप्लिकेशन का कॉन्टेंट, सिस्टम बार और डिसप्ले कटआउट से बच सकता है. साथ ही, यह WindowInsets का सीधे तौर पर इस्तेमाल करने से ज़्यादा आसान हो सकता है.
  • पसंद के मुताबिक बनाया जा सकता है: डेवलपर, कॉन्टेंट को पसंद के मुताबिक रूलर के साथ अलाइन कर सकते हैं. साथ ही, पसंद के मुताबिक लेआउट की मदद से, अपने लेआउट पर सटीक कंट्रोल पा सकते हैं.

WindowInsetsRulers के नुकसान

  • इसका इस्तेमाल मेज़रमेंट के लिए नहीं किया जा सकता: यह प्लेसमेंट फ़ेज़ के दौरान काम करता है. इसलिए, इसके ज़रिए दी गई पोज़िशन की जानकारी, पहले के मेज़रमेंट फ़ेज़ के दौरान उपलब्ध नहीं होती.

अपने कॉन्टेंट को मॉडिफ़ायर के तरीकों के साथ अलाइन करना

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

लागू नहीं

NavigationBars

SafeDrawing

लागू नहीं (इसके बजाय, StatusBar, CaptionBar, NavigationBar का इस्तेमाल करें)

StatusBar

Modifier.fitInside और Modifier.fitOutside का इस्तेमाल करने के लिए, कंपोज़ेबल पर पाबंदियां लगाना ज़रूरी है. इसका मतलब है कि आपको Modifier.size या Modifier.fillMaxSize जैसे मॉडिफ़ायर तय करने होंगे.

SafeDrawing और SystemBars पर Modifier.fitOutside जैसे कुछ रूलर, एक से ज़्यादा रूलर दिखाते हैं. ऐसे में, Android, कंपोज़ेबल को बाईं, ऊपर, दाईं, नीचे से किसी एक रूलर का इस्तेमाल करके रखता है.

Modifier.fitInside की मदद से, आईएमई से बचना

Modifier.fitInside की मदद से, आईएमई वाले सबसे नीचे के एलिमेंट को मैनेज करने के लिए, 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.fitInsider के साथ, 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)
            }
        }
    }
}

यहां दिए गए वीडियो में, आईएमई इनसेट के इस्तेमाल से जुड़ी समस्या का उदाहरण दिखाया गया है. यह समस्या, बाईं ओर मौजूद इमेज में अपस्ट्रीम पैरंट की वजह से हुई है. साथ ही, दाईं ओर, इस समस्या को ठीक करने के लिए, पसंद के मुताबिक रूलर का इस्तेमाल किया गया है. TextField कंपोज़ेबल के नीचे, ज़्यादा पैडिंग दिख रही है, क्योंकि पैरंट ने नेविगेशन बार की पैडिंग का इस्तेमाल नहीं किया. दाईं ओर मौजूद इमेज में, चाइल्ड को सही जगह पर रखा गया है. इसके लिए, पसंद के मुताबिक रूलर का इस्तेमाल किया गया है. यह जानकारी, कोड के पिछले उदाहरण में देखी जा सकती है.

इस बात की पुष्टि करना कि पैरंट पर पाबंदियां लगी हैं

WindowInsetsRulers का सुरक्षित तरीके से इस्तेमाल करने के लिए, पक्का करें कि पैरंट, मान्य पाबंदियां उपलब्ध कराता हो. पैरंट का साइज़ तय होना चाहिए. साथ ही, यह WindowInsetsRulers का इस्तेमाल करने वाले चाइल्ड के साइज़ पर निर्भर नहीं हो सकता. पैरंट कंपोज़ेबल पर, fillMaxSize या साइज़ में बदलाव करने वाले अन्य मॉडिफ़ायर का इस्तेमाल करें.

इसी तरह, WindowInsetsRulers का इस्तेमाल करने वाले कंपोज़ेबल को, स्क्रोल करने वाले कंटेनर में रखने पर, अनचाहा व्यवहार हो सकता है. जैसे, verticalScroll. इसकी वजह यह है कि स्क्रोल करने वाला कंटेनर, ऊंचाई की असीमित पाबंदियां उपलब्ध कराता है. ये पाबंदियां, रूलर के लॉजिक के साथ काम नहीं करती हैं.