विंडो इनसेट सेट अप करना

जब आपकी गतिविधि सभी इनसेट को मैनेज करने का कंट्रोल ले लेती है, तब Compose API का इस्तेमाल करके यह पुष्टि की जा सकती है कि कॉन्टेंट छिपा नहीं है और इंटरैक्ट किए जा सकने वाले एलिमेंट, सिस्टम यूज़र इंटरफ़ेस (यूआई) के साथ ओवरलैप नहीं हो रहे हैं. ये एपीआई, आपके ऐप्लिकेशन के लेआउट को इंसर्ट में हुए बदलावों के साथ सिंक करते हैं.

पैडिंग या साइज़ मॉडिफ़ायर का इस्तेमाल करके, इनसेट मैनेज करना

उदाहरण के लिए, यहां आपके पूरे ऐप्लिकेशन के कॉन्टेंट में इनसेट लागू करने का सबसे बुनियादी तरीका बताया गया है:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    enableEdgeToEdge()

    setContent {
        Box(Modifier.safeDrawingPadding()) {
            // the rest of the app
        }
    }
}

इस स्निपेट में, safeDrawing विंडो इंसर्ट को ऐप्लिकेशन के पूरे कॉन्टेंट के चारों ओर पैडिंग के तौर पर इस्तेमाल किया गया है. इससे यह पक्का होता है कि इंटरैक्ट किए जा सकने वाले एलिमेंट, सिस्टम यूआई के साथ ओवरलैप न करें. इसका यह भी मतलब है कि ऐप्लिकेशन का कोई भी हिस्सा, किनारे से किनारे तक इफ़ेक्ट पाने के लिए सिस्टम यूआई के पीछे नहीं दिखेगा. पूरी विंडो का बेहतर तरीके से इस्तेमाल करने के लिए, आपको स्क्रीन-दर-स्क्रीन या कॉम्पोनेंट-दर-कॉम्पोनेंट के आधार पर, यह तय करना होगा कि इंसर्ट कहां लागू किए जाएं.

ये सभी इंसर्ट टाइप, IME ऐनिमेशन के साथ अपने-आप ऐनिमेट हो जाते हैं. इन्हें एपीआई 21 पर वापस ले जाया गया है. इसके अलावा, इन इनसेट का इस्तेमाल करने वाले आपके सभी लेआउट भी अपने-आप ऐनिमेट हो जाते हैं, क्योंकि इनसेट की वैल्यू बदल जाती हैं.

अपने कंपोज़ेबल लेआउट को अडजस्ट करने के लिए, इनसेट को तीन तरीकों से मैनेज किया जा सकता है:

पैडिंग मॉडिफ़ायर

Modifier.windowInsetsPadding(windowInsets: WindowInsets), विंडो इंसर्ट को पैडिंग के तौर पर लागू करता है. यह ठीक वैसे ही काम करता है जैसे Modifier.padding करता है. उदाहरण के लिए, Modifier.windowInsetsPadding(WindowInsets.safeDrawing) सभी चार किनारों पर पैडिंग के तौर पर, सेफ़ ड्रॉइंग इनसेट लागू करता है.

सबसे ज़्यादा इस्तेमाल किए जाने वाले इंसर्ट टाइप के लिए, कई यूटिलिटी मेथड भी पहले से मौजूद हैं. Modifier.safeDrawingPadding() ऐसा ही एक तरीका है, जो Modifier.windowInsetsPadding(WindowInsets.safeDrawing) के बराबर है. अन्य इंसर्ट टाइप के लिए, मिलते-जुलते मॉडिफ़ायर मौजूद हैं.

इन्सर्ट साइज़ मॉडिफ़ायर

नीचे दिए गए मॉडिफ़ायर, विंडो इंसर्ट की जगह तय करते हैं. इसके लिए, कॉम्पोनेंट का साइज़ इंसर्ट के साइज़ के बराबर सेट किया जाता है:

Modifier.windowInsetsStartWidth(windowInsets: WindowInsets)

windowInsets के शुरुआती हिस्से को चौड़ाई के तौर पर लागू करता है (जैसे, Modifier.width)

Modifier.windowInsetsEndWidth(windowInsets: WindowInsets)

windowInsets के आखिर वाले हिस्से को चौड़ाई के तौर पर लागू करता है (जैसे कि Modifier.width)

Modifier.windowInsetsTopHeight(windowInsets: WindowInsets)

windowInsets के सबसे ऊपर वाले हिस्से को ऊंचाई के तौर पर इस्तेमाल करता है (जैसे, Modifier.height)

Modifier.windowInsetsBottomHeight(windowInsets: WindowInsets)

windowInsets के सबसे नीचे वाले हिस्से को ऊंचाई के तौर पर लागू करता है (जैसे कि Modifier.height)

ये मॉडिफ़ायर, खास तौर पर ऐसे Spacer का साइज़ तय करने के लिए काम आते हैं जो इनसेट की जगह लेता है:

LazyColumn(
    Modifier.imePadding()
) {
    // Other content
    item {
        Spacer(
            Modifier.windowInsetsBottomHeight(
                WindowInsets.systemBars
            )
        )
    }
}

इनसेट के लिए खपत

इनसेट पैडिंग मॉडिफ़ायर (windowInsetsPadding और safeDrawingPadding जैसे हेल्पर) अपने-आप इनसेट के उस हिस्से का इस्तेमाल करते हैं जिसे पैडिंग के तौर पर लागू किया जाता है. कंपोज़िशन ट्री में ज़्यादा जानकारी देते समय, नेस्ट किए गए इनसेट पैडिंग मॉडिफ़ायर और इनसेट साइज़ मॉडिफ़ायर को पता होता है कि इनसेट का कुछ हिस्सा, पहले ही आउटर इनसेट पैडिंग मॉडिफ़ायर इस्तेमाल कर चुके हैं. इसलिए, वे इनसेट के उसी हिस्से का इस्तेमाल एक से ज़्यादा बार नहीं करते. ऐसा करने से, बहुत ज़्यादा अतिरिक्त जगह मिल सकती है.

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

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

यहां पहले वाले LazyColumn उदाहरण को देखें. इसमें LazyColumn को imePadding मॉडिफ़ायर की मदद से रीसाइज़ किया जा रहा है. LazyColumn के अंदर, आखिरी आइटम को सिस्टम बार के सबसे नीचे की ऊंचाई के हिसाब से साइज़ किया जाता है:

LazyColumn(
    Modifier.imePadding()
) {
    // Other content
    item {
        Spacer(
            Modifier.windowInsetsBottomHeight(
                WindowInsets.systemBars
            )
        )
    }
}

जब IME बंद होता है, तो imePadding() मॉडिफ़ायर कोई पैडिंग लागू नहीं करता, क्योंकि IME की कोई ऊंचाई नहीं होती. imePadding() मॉडिफ़ायर कोई पैडिंग लागू नहीं कर रहा है, इसलिए कोई इनसेट इस्तेमाल नहीं किया जा रहा है. साथ ही, Spacer की ऊंचाई, सिस्टम बार की निचली ओर के साइज़ के बराबर होगी.

IME खुलने पर, IME इनसेट, IME के साइज़ के हिसाब से ऐनिमेट होते हैं. साथ ही, IME खुलने पर imePadding() मॉडिफ़ायर, LazyColumn का साइज़ बदलने के लिए बॉटम पैडिंग लागू करना शुरू कर देता है. imePadding() मॉडिफ़ायर, बॉटम पैडिंग लागू करना शुरू करता है. साथ ही, यह इनसेट की उस मात्रा का इस्तेमाल करना भी शुरू कर देता है. इसलिए, Spacer की ऊंचाई कम होने लगती है, क्योंकि सिस्टम बार के लिए स्पेसिंग का हिस्सा पहले ही imePadding() मॉडिफ़ायर से लागू किया जा चुका है. जब imePadding() मॉडिफ़ायर, सिस्टम बार से ज़्यादा बॉटम पैडिंग लागू करता है, तब Spacer की ऊंचाई शून्य होती है.

IME बंद होने पर, बदलाव उल्टे क्रम में होते हैं: Spacer की ऊंचाई शून्य से बढ़ने लगती है. ऐसा तब होता है, जब imePadding(), सिस्टम बार के निचले हिस्से से कम जगह लेता है. आखिर में, Spacer की ऊंचाई, सिस्टम बार के निचले हिस्से की ऊंचाई के बराबर हो जाती है. ऐसा तब होता है, जब IME पूरी तरह से ऐनिमेट हो जाता है.

दूसरी इमेज. TextField के साथ एज-टू-एज लेज़ी कॉलम.

यह व्यवहार, सभी windowInsetsPadding मॉडिफ़ायर के बीच बातचीत के ज़रिए पूरा किया जाता है. इसे कुछ अन्य तरीकों से भी बदला जा सकता है.

Modifier.consumeWindowInsets(insets: WindowInsets) भी Modifier.windowInsetsPadding की तरह ही इनसेट का इस्तेमाल करता है. हालांकि, यह इस्तेमाल किए गए इनसेट को पैडिंग के तौर पर लागू नहीं करता. यह इनसेट साइज़ मॉडिफ़ायर के साथ इस्तेमाल करने पर काम आता है. इससे सिबलिंग को यह पता चलता है कि कुछ इनसेट पहले ही इस्तेमाल किए जा चुके हैं:

Column(Modifier.verticalScroll(rememberScrollState())) {
    Spacer(Modifier.windowInsetsTopHeight(WindowInsets.systemBars))

    Column(
        Modifier.consumeWindowInsets(
            WindowInsets.systemBars.only(WindowInsetsSides.Vertical)
        )
    ) {
        // content
        Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.ime))
    }

    Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.systemBars))
}

Modifier.consumeWindowInsets(paddingValues: PaddingValues), WindowInsets आर्ग्युमेंट वाले वर्शन की तरह ही काम करता है. हालाँकि, यह इस्तेमाल करने के लिए कोई भी PaddingValues लेता है. यह बच्चों को यह बताने के लिए काम आता है कि इंसर्ट पैडिंग मॉडिफ़ायर के अलावा, किसी अन्य तरीके से पैडिंग या स्पेसिंग दी गई है. जैसे, सामान्य Modifier.padding या तय ऊंचाई वाले स्पेसर:

Column(Modifier.padding(16.dp).consumeWindowInsets(PaddingValues(16.dp))) {
    // content
    Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.ime))
}

अगर आपको रॉ विंडो इंसर्ट का इस्तेमाल करना है, तो सीधे तौर पर WindowInsets वैल्यू का इस्तेमाल करें. इसके अलावा, WindowInsets.asPaddingValues() का इस्तेमाल करके, इंसर्ट के PaddingValues को वापस लाएं. इन पर इस्तेमाल का कोई असर नहीं पड़ता. हालांकि, यहां दी गई चेतावनियों की वजह से, जहां भी हो सके वहां विंडो इंसर्ट पैडिंग मॉडिफ़ायर और विंडो इंसर्ट साइज़ मॉडिफ़ायर का इस्तेमाल करें.

इनसेट और Jetpack Compose के फ़ेज़

Compose, AndroidX के कोर एपीआई का इस्तेमाल करके, इनसेट को अपडेट और ऐनिमेट करता है. ये एपीआई, इनसेट को मैनेज करने वाले प्लैटफ़ॉर्म एपीआई का इस्तेमाल करते हैं. उस प्लैटफ़ॉर्म के व्यवहार की वजह से, इनसेट का Jetpack Compose के फ़ेज़ के साथ खास संबंध होता है.

इनसेट की वैल्यू, कंपोज़िशन फ़ेज़ के बाद और लेआउट फ़ेज़ के पहले अपडेट की जाती हैं. इसका मतलब है कि कंपोज़िशन में इंसर्ट की वैल्यू को पढ़ने के लिए, आम तौर पर इंसर्ट की ऐसी वैल्यू का इस्तेमाल किया जाता है जो एक फ़्रेम बाद में अपडेट होती है. इस पेज पर बताए गए बिल्ट-इन मॉडिफ़ायर, लेआउट फ़ेज़ तक इंसर्ट की वैल्यू का इस्तेमाल करने में देरी करने के लिए बनाए गए हैं. इससे यह पक्का होता है कि इंसर्ट की वैल्यू का इस्तेमाल उसी फ़्रेम पर किया जाए जिस पर उन्हें अपडेट किया गया है.