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

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

  1. Android 15 और इसके बाद के वर्शन पर एज-टू-एज डिसप्ले की सुविधा लागू करने के लिए, Android 15 (एपीआई लेवल 35) या इसके बाद के वर्शन को टारगेट करें. आपका ऐप्लिकेशन, सिस्टम यूज़र इंटरफ़ेस (यूआई) के पीछे दिखता है. इनसेट को मैनेज करके, अपने ऐप्लिकेशन के यूज़र इंटरफ़ेस (यूआई) में बदलाव किया जा सकता है.
  2. इसके अलावा, Activity.onCreate() में enableEdgeToEdge() को कॉल करें. इससे आपका ऐप्लिकेशन, Android के पिछले वर्शन पर एज-टू-एज डिसप्ले फ़ॉर्मैट में दिखेगा.
  3. अपनी गतिविधि की AndroidManifest.xml एंट्री में android:windowSoftInputMode="adjustResize" सेट करें. इस सेटिंग की मदद से, आपका ऐप्लिकेशन सॉफ़्टवेयर आईएमई के साइज़ को इंसर्ट के तौर पर पा सकता है. इससे, आईएमई के दिखने और गायब होने पर, सही लेआउट और पैडिंग लागू करने में मदद मिलती है.

    <!-- In your AndroidManifest.xml file: -->
    <activity
      android:name=".ui.MainActivity"
      android:label="@string/app_name"
      android:windowSoftInputMode="adjustResize"
      android:theme="@style/Theme.MyApplication"
      android:exported="true">
    

Compose API का इस्तेमाल करना

जब आपकी गतिविधि सभी इनसेट को मैनेज करने का कंट्रोल ले लेती है, तब 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 मॉडिफ़ायर की मदद से 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 के फ़ेज़ के साथ खास संबंध होता है.

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