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

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

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.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)
            }
        }
    }
}

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

पुष्टि करें कि पैरंट एलिमेंट पर पाबंदी लगाई गई है

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

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