अपने ऐप्लिकेशन में कॉन्टेंट को एक से दूसरे किनारे तक दिखाएं और Compose में विंडो इनसेट को हैंडल करें

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

WindowInsets, सिस्टम यूआई के बारे में जानकारी देता है. इससे यह पक्का किया जा सकता है कि आपका ऐप्लिकेशन सही जगह पर दिखे और सिस्टम यूआई से आपका यूआई छिप न जाए.

सिस्टम बार के पीछे ड्रॉ करने के लिए, किनारे से किनारे तक जाना
पहला डायग्राम. सिस्टम बार के पीछे ड्रॉ करने के लिए, किनारे से किनारे तक जाना.

Android 14 (एपीआई लेवल 34) और इससे पहले के वर्शन पर, आपके ऐप्लिकेशन का यूज़र इंटरफ़ेस (यूआई), डिफ़ॉल्ट रूप से सिस्टम बार और डिसप्ले कटआउट के नीचे नहीं दिखता.

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

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

इनसेट की बुनियादी बातें

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

इनसेट की मदद से, सिस्टम यूज़र इंटरफ़ेस (यूआई) के साइज़ और उसे कहां रखा गया है, इसकी जानकारी दी जाती है.

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

Android में पहले से मौजूद इनसेट टाइप, WindowInsets के ज़रिए उपलब्ध हैं:

WindowInsets.statusBars

स्टेटस बार के बारे में बताने वाले इनसेट. ये सिस्टम के सबसे ऊपर मौजूद यूज़र इंटरफ़ेस (यूआई) बार हैं. इनमें सूचना के आइकॉन और अन्य इंडिकेटर होते हैं.

WindowInsets.statusBarsIgnoringVisibility

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

WindowInsets.navigationBars

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

WindowInsets.navigationBarsIgnoringVisibility

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

WindowInsets.captionBar

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

WindowInsets.captionBarIgnoringVisibility

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

WindowInsets.systemBars

सिस्टम बार इनसेट का यूनियन, जिसमें स्टेटस बार, नेविगेशन बार, और कैप्शन बार शामिल हैं.

WindowInsets.systemBarsIgnoringVisibility

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

WindowInsets.ime

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

WindowInsets.imeAnimationSource

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

WindowInsets.imeAnimationTarget

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

WindowInsets.tappableElement

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

WindowInsets.tappableElementIgnoringVisibility

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

WindowInsets.systemGestures

इनसेट की संख्या दिखाने वाले इनसेट, जहां सिस्टम नेविगेशन के लिए जेस्चर को इंटरसेप्ट करेगा. ऐप्लिकेशन, Modifier.systemGestureExclusion की मदद से, मैन्युअल तरीके से यह तय कर सकते हैं कि इनमें से कुछ ही जेस्चर को मैनेज किया जाए.

WindowInsets.mandatorySystemGestures

सिस्टम जेस्चर का एक सबसेट, जिसे हमेशा सिस्टम मैनेज करेगा. साथ ही, Modifier.systemGestureExclusion की मदद से इससे ऑप्ट आउट नहीं किया जा सकता.

WindowInsets.displayCutout

इनसेट, डिसप्ले कटआउट (नॉच या पिनहोल) के साथ ओवरलैप होने से बचने के लिए, ज़रूरी स्पेस की जानकारी देते हैं.

WindowInsets.waterfall

इनसे वॉटरफ़ॉल डिसप्ले के घुमावदार हिस्सों को दिखाया जाता है. वॉटरफ़ॉल डिसप्ले में, स्क्रीन के किनारों पर ऐसे हिस्से होते हैं जो घुमावदार होते हैं. यहां स्क्रीन, डिवाइस के किनारों पर रैप होने लगती है.

इनमें से तीन "सुरक्षित" इनसेट टाइप होते हैं, जिनसे यह पक्का होता है कि कॉन्टेंट को छिपाया न गया हो:

ये "सुरक्षित" इनसेट टाइप, प्लैटफ़ॉर्म के इनसेट के आधार पर, कॉन्टेंट को अलग-अलग तरीकों से सुरक्षित रखते हैं:

  • WindowInsets.safeDrawing का इस्तेमाल करके, उस कॉन्टेंट को सुरक्षित करें जिसे किसी भी सिस्टम यूज़र इंटरफ़ेस (यूआई) के नीचे नहीं दिखाना है. इनसेट का सबसे आम इस्तेमाल यह है: सिस्टम यूज़र इंटरफ़ेस (यूआई) से छिपे हुए कॉन्टेंट को खींचने से रोकने के लिए (कुछ हद तक या पूरी तरह से).
  • जेस्चर की मदद से कॉन्टेंट को सुरक्षित करने के लिए, WindowInsets.safeGestures का इस्तेमाल करें. इससे, सिस्टम जेस्चर और ऐप्लिकेशन जेस्चर (जैसे कि बॉटम शीट, कैरसेल या गेम में) के बीच होने वाली गड़बड़ी से बचा जा सकता है.
  • WindowInsets.safeContent का इस्तेमाल, WindowInsets.safeDrawing और WindowInsets.safeGestures के कॉम्बिनेशन के तौर पर करें. इससे यह पक्का किया जा सकता है कि कॉन्टेंट में कोई विज़ुअल ओवरलैप न हो और कोई जेस्चर ओवरलैप न हो.

इनसेट का सेटअप

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

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

    <!-- 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 विंडो इनसेट लागू करता है. इससे यह पक्का होता है कि इंटरैक्ट किए जा सकने वाले एलिमेंट, सिस्टम यूज़र इंटरफ़ेस (यूआई) के साथ ओवरलैप न हों. इसका यह भी मतलब है कि ऐप्लिकेशन का कोई भी हिस्सा, किनारों तक दिखने वाला इफ़ेक्ट पाने के लिए, सिस्टम यूज़र इंटरफ़ेस (यूआई) के पीछे नहीं दिखेगा. पूरी विंडो का पूरा फ़ायदा पाने के लिए, आपको यह तय करना होगा कि इनसेट को स्क्रीन के हिसाब से या कॉम्पोनेंट के हिसाब से कहां लागू करना है.

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

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

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

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 के उदाहरण को देखें. इसमें imePadding मॉडिफ़ायर की मदद से, LazyColumn का साइज़ बदला जा रहा है. 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 बंद होने पर, ये बदलाव उलटे क्रम में होते हैं: imePadding() के सिस्टम बार के सबसे नीचे वाले हिस्से से कम लागू होने पर, Spacer शून्य की ऊंचाई से बड़ा होना शुरू हो जाता है. आखिर में, IME पूरी तरह से ऐनिमेशन के साथ बंद होने पर, Spacer की ऊंचाई, सिस्टम बार के सबसे नीचे वाले हिस्से की ऊंचाई से मेल खाती है.

दूसरी इमेज. 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 के चरणों से खास संबंध है.

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

WindowInsets के साथ कीबोर्ड IME ऐनिमेशन

स्क्रोल किए जा रहे कंटेनर पर Modifier.imeNestedScroll() लागू किया जा सकता है, ताकि कंटेनर के सबसे नीचे स्क्रोल करने पर, IME अपने-आप खुले और बंद हो जाए.

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

        WindowCompat.setDecorFitsSystemWindows(window, false)

        setContent {
            MaterialTheme {
                MyScreen()
            }
        }
    }
}

@OptIn(ExperimentalLayoutApi::class)
@Composable
fun MyScreen() {
    Box {
        LazyColumn(
            modifier = Modifier
                .fillMaxSize() // fill the entire window
                .imePadding() // padding for the bottom for the IME
                .imeNestedScroll(), // scroll IME at the bottom
            content = { }
        )
        FloatingActionButton(
            modifier = Modifier
                .align(Alignment.BottomEnd)
                .padding(16.dp) // normal 16dp of padding for FABs
                .navigationBarsPadding() // padding for navigation bar
                .imePadding(), // padding for when IME appears
            onClick = { }
        ) {
            Icon(imageVector = Icons.Filled.Add, contentDescription = "Add")
        }
    }
}

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

Material 3 कॉम्पोनेंट के लिए इनसेट की सुविधा

इस्तेमाल करने में आसानी के लिए, Material 3 के कई पहले से मौजूद कॉम्पोज़ेबल (androidx.compose.material3), इनसेट को खुद मैनेज करते हैं. यह इस बात पर निर्भर करता है कि Material के स्पेसिफ़िकेशन के मुताबिक, आपके ऐप्लिकेशन में कॉम्पोज़ेबल को कैसे रखा गया है.

इनसेट में कॉम्पोज़ेबल हैंडलिंग

यहां उन Material Components की सूची दी गई है जो इनसेट को अपने-आप मैनेज करते हैं.

ऐप्लिकेशन बार

  • TopAppBar / SmallTopAppBar / CenterAlignedTopAppBar / MediumTopAppBar / LargeTopAppBar: सिस्टम बार के ऊपर और हॉरिज़ॉन्टल हिस्सों को पैडिंग के तौर पर लागू करता है, क्योंकि इसका इस्तेमाल विंडो के सबसे ऊपर किया जाता है.
  • BottomAppBar: सिस्टम बार के नीचे और हॉरिज़ॉन्टल हिस्सों को पैडिंग के तौर पर लागू करता है.

कॉन्टेंट कंटेनर

  • ModalDrawerSheet / DismissibleDrawerSheet / PermanentDrawerSheet (मोडल नेविगेशन ड्रॉअर में मौजूद कॉन्टेंट): कॉन्टेंट में वर्टिकल और स्टार्ट इनसेट लागू करता है.
  • ModalBottomSheet: बॉटम इनसेट लागू करता है.
  • NavigationBar : नीचे और हॉरिज़ॉन्टल इनसेट लागू करता है.
  • NavigationRail: वर्टिकल और स्टार्ट इनसेट लागू करता है.

मचान

डिफ़ॉल्ट रूप से, Scaffold, पैरामीटर paddingValues के तौर पर इनसेट उपलब्ध कराता है, ताकि आप उन्हें इस्तेमाल कर सकें. Scaffold, कॉन्टेंट में इनसेट लागू नहीं करता. यह आपकी ज़िम्मेदारी है. उदाहरण के लिए, Scaffold के अंदर LazyColumn के साथ इनसेट का इस्तेमाल करने के लिए:

Scaffold { innerPadding ->
    // innerPadding contains inset information for you to use and apply
    LazyColumn(
        // consume insets as scaffold doesn't do it by default
        modifier = Modifier.consumeWindowInsets(innerPadding),
        contentPadding = innerPadding
    ) {
        items(count = 100) {
            Box(
                Modifier
                    .fillMaxWidth()
                    .height(50.dp)
                    .background(colors[it % colors.size])
            )
        }
    }
}

डिफ़ॉल्ट इनसेट बदलना

कॉम्पोज़ेबल के व्यवहार को कॉन्फ़िगर करने के लिए, कॉम्पोज़ेबल में पास किए गए windowInsets पैरामीटर को बदला जा सकता है. इस पैरामीटर के तौर पर, किसी दूसरी तरह का विंडो इनसेट लागू किया जा सकता है. इसके अलावा, खाली इंस्टेंस:WindowInsets(0, 0, 0, 0) पास करके भी इसे बंद किया जा सकता है.

उदाहरण के लिए, LargeTopAppBar पर इनसेट हैंडल करने की सुविधा बंद करने के लिए, windowInsets पैरामीटर को खाली इंस्टेंस पर सेट करें:

LargeTopAppBar(
    windowInsets = WindowInsets(0, 0, 0, 0),
    title = {
        Text("Hi")
    }
)

View सिस्टम इनसेट के साथ इंटरऑपरेट करना

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

उदाहरण के लिए, अगर आपका सबसे बाहरी लेआउट Android View लेआउट है, तो आपको View सिस्टम में इनसेट का इस्तेमाल करना चाहिए और Compose के लिए उन्हें अनदेखा करना चाहिए. इसके अलावा, अगर आपका सबसे बाहरी लेआउट कोई कॉम्पोज़ेबल है, तो आपको Compose में इनसेट का इस्तेमाल करना चाहिए. साथ ही, AndroidView कॉम्पोज़ेबल को उसी हिसाब से पैड करना चाहिए.

डिफ़ॉल्ट रूप से, हर ComposeView, WindowInsetsCompat लेवल पर सभी इनसेट का इस्तेमाल करता है. इस डिफ़ॉल्ट व्यवहार को बदलने के लिए, ComposeView.consumeWindowInsets को false पर सेट करें.

सिस्टम बार की सुरक्षा

जब आपका ऐप्लिकेशन SDK टूल 35 या उसके बाद के वर्शन को टारगेट करता है, तो एज-टू-एज डिसप्ले लागू हो जाता है. सिस्टम स्टेटस बार और जेस्चर नेविगेशन बार पारदर्शी होते हैं. हालांकि, तीन बटन वाला नेविगेशन बार पारभासक होता है.

नेविगेशन के बैकग्राउंड में, डिफ़ॉल्ट रूप से दिखने वाले तीन बटन की पारदर्शी सुरक्षा हटाने के लिए, Window.setNavigationBarContrastEnforced को false पर सेट करें.

संसाधन