WebView, कॉन्टेंट के अलाइनमेंट को मैनेज करने के लिए दो व्यूपोर्ट का इस्तेमाल करता है: लेआउट व्यूपोर्ट (पेज का साइज़) और विज़ुअल व्यूपोर्ट (पेज का वह हिस्सा जो उपयोगकर्ता को असल में दिखता है). आम तौर पर, लेआउट व्यूपोर्ट स्टैटिक होता है. हालांकि, विज़ुअल व्यूपोर्ट में डाइनैमिक तौर पर बदलाव होता है. ऐसा तब होता है, जब उपयोगकर्ता ज़ूम या स्क्रोल करते हैं या जब सिस्टम के यूज़र इंटरफ़ेस (यूआई) एलिमेंट (जैसे, सॉफ़्टवेयर कीबोर्ड) दिखते हैं.
सुविधा के साथ काम करने की क्षमता
विंडो इनसेट के लिए वेबव्यू की सुविधा में समय के साथ बदलाव हुए हैं, ताकि वेब कॉन्टेंट के व्यवहार को नेटिव Android ऐप्लिकेशन की उम्मीदों के मुताबिक बनाया जा सके:
| Milestone | सुविधा जोड़ी गई | दायरा |
|---|---|---|
| M136 | displayCutout() और systemBars(), सीएसएस safe-area-insets के ज़रिए काम करते हैं. |
सिर्फ़ फ़ुलस्क्रीन वेबव्यू. |
| M139 | ime() (इनपुट मेथड एडिटर, जो कि एक कीबोर्ड है) के लिए सहायता. इसके लिए, विज़ुअल व्यूपोर्ट का साइज़ बदला जाता है. |
सभी वेबव्यू. |
| M144 | displayCutout() और systemBars() के लिए सहायता. |
सभी वेबव्यू (चाहे वे फ़ुलस्क्रीन मोड में हों या नहीं). |
ज़्यादा जानकारी के लिए, WindowInsetsCompat देखें.
मुख्य गेमप्ले
WebView, इनसेट को दो मुख्य तरीकों से मैनेज करता है:
सुरक्षित एरिया (
displayCutout,systemBars): WebView, इन डाइमेंशन को सीएसएस safe-area-inset-* वैरिएबल के ज़रिए वेब कॉन्टेंट पर फ़ॉरवर्ड करता है. इससे डेवलपर, अपने इंटरैक्टिव एलिमेंट (जैसे, नेविगेशन बार) को नॉच या स्टेटस बार से छिपने से रोक सकते हैं.इनपुट मेथड एडिटर (आईएमई) का इस्तेमाल करके, विज़ुअल व्यूपोर्ट का साइज़ बदलना: M139 से, इनपुट मेथड एडिटर (आईएमई) सीधे तौर पर विज़ुअल व्यूपोर्ट का साइज़ बदलता है. साइज़ बदलने का यह तरीका, WebView-Window इंटरसेक्शन पर भी आधारित है. उदाहरण के लिए, Android के मल्टीटास्किंग मोड में, अगर WebView का निचला हिस्सा विंडो के निचले हिस्से से 200 डीपी नीचे तक फैला है, तो विज़ुअल व्यूपोर्ट, WebView के साइज़ से 200 डीपी छोटा होता है. विज़ुअल व्यूपोर्ट का साइज़ बदलने की यह सुविधा (आईएमई और वेबव्यू-विंडो इंटरसेक्शन, दोनों के लिए), सिर्फ़ वेबव्यू के सबसे निचले हिस्से पर लागू होती है. इस तरीके से, बाईं, दाईं या ऊपर की ओर ओवरलैप होने वाले हिस्से का साइज़ नहीं बदला जा सकता. इसका मतलब है कि उन किनारों पर दिखने वाले डॉक किए गए कीबोर्ड, विज़ुअल व्यूपोर्ट के साइज़ में बदलाव नहीं करते.
पहले, विज़ुअल व्यूपोर्ट फ़िक्स रहता था. इस वजह से, इनपुट फ़ील्ड अक्सर कीबोर्ड के पीछे छिप जाते थे. व्यूपोर्ट का साइज़ बदलने पर, पेज का दिखने वाला हिस्सा डिफ़ॉल्ट रूप से स्क्रोल किया जा सकता है. इससे यह पक्का होता है कि उपयोगकर्ता, छिपे हुए कॉन्टेंट तक पहुंच सकें.
बाउंड और ओवरलैप लॉजिक
WebView को इनसेट की वैल्यू शून्य से ज़्यादा सिर्फ़ तब मिलनी चाहिए, जब सिस्टम के यूज़र इंटरफ़ेस (यूआई) एलिमेंट (बार, डिसप्ले कटआउट या कीबोर्ड), WebView की स्क्रीन की सीमाओं को सीधे तौर पर ओवरलैप करते हों. अगर कोई वेबव्यू, इन यूज़र इंटरफ़ेस (यूआई) एलिमेंट को ओवरलैप नहीं करता है, तो उसे इनसेट की वैल्यू शून्य मिलनी चाहिए. जैसे, अगर कोई वेबव्यू स्क्रीन के बीच में है और सिस्टम बार को टच नहीं करता है.
इस डिफ़ॉल्ट लॉजिक को बदलने और वेब कॉन्टेंट को सिस्टम के डाइमेंशन के हिसाब से दिखाने के लिए, setOnApplyWindowInsetsListener तरीके का इस्तेमाल करें. साथ ही, लिसनर से ओरिजनल और बिना बदलाव वाला windowInsets ऑब्जेक्ट दिखाएं. इससे कोई फ़र्क़ नहीं पड़ता कि कॉन्टेंट ओवरलैप हो रहा है या नहीं. सिस्टम के डाइमेंशन की पूरी जानकारी देने से, डिज़ाइन को एक जैसा बनाए रखने में मदद मिल सकती है. इससे वेब कॉन्टेंट को डिवाइस के हार्डवेयर के साथ अलाइन किया जा सकता है. भले ही, WebView की मौजूदा पोज़िशन कुछ भी हो. इससे यह पक्का होता है कि वेबव्यू के स्क्रीन के किनारों तक जाने या बड़ा होने पर, ट्रांज़िशन आसानी से हो.
Kotlin
ViewCompat.setOnApplyWindowInsetsListener(myWebView) { _, windowInsets -> // By returning the original windowInsets object, we override the default // behavior that zeroes out system insets (like system bars or display // cutouts) when they don't directly overlap the WebView's screen bounds. windowInsets }
Java
ViewCompat.setOnApplyWindowInsetsListener(myWebView, (v, windowInsets) -> { // By returning the original windowInsets object, we override the default // behavior that zeroes out system insets (like system bars or display // cutouts) when they don't directly overlap the WebView's screen bounds. return windowInsets; });
साइज़ बदलने वाले इवेंट मैनेज करना
कीबोर्ड दिखने पर, अब विज़ुअल व्यूपोर्ट का साइज़ बदल जाता है. इस वजह से, वेब कोड को साइज़ बदलने के इवेंट ज़्यादा बार दिख सकते हैं. डेवलपर को यह पक्का करना होगा कि उनका कोड, एलिमेंट फ़ोकस को हटाकर, साइज़ बदलने वाले इन इवेंट पर प्रतिक्रिया न दे. ऐसा करने से, फ़ोकस हटने और कीबोर्ड बंद होने का एक लूप बन जाता है. इससे उपयोगकर्ता इनपुट नहीं दे पाता:
- जब उपयोगकर्ता किसी इनपुट एलिमेंट पर फ़ोकस करता है.
- कीबोर्ड दिखता है, जिससे साइज़ बदलने वाला इवेंट ट्रिगर होता है.
- वेबसाइट का कोड, साइज़ बदलने के जवाब में फ़ोकस को हटा देता है.
- फ़ोकस हटने की वजह से कीबोर्ड छिप जाता है.
इस समस्या को कम करने के लिए, वेब-साइड लिसनर की समीक्षा करें. इससे यह पक्का किया जा सकेगा कि व्यूपोर्ट में होने वाले बदलावों से, अनजाने में blur() JavaScript फ़ंक्शन या फ़ोकस-क्लियरिंग व्यवहार ट्रिगर न हों.
इनसेट हैंडलिंग लागू करना
WebView की डिफ़ॉल्ट सेटिंग, ज़्यादातर ऐप्लिकेशन के लिए अपने-आप काम करती हैं. हालांकि, अगर आपका ऐप्लिकेशन कस्टम लेआउट का इस्तेमाल करता है, तो वेब कॉन्टेंट और नेटिव यूज़र इंटरफ़ेस (यूआई) के साथ काम करने के तरीके को बेहतर बनाने के लिए, यहां दिए गए तरीके इस्तेमाल किए जा सकते हैं. उदाहरण के लिए, स्टेटस बार या कीबोर्ड के लिए अपनी पैडिंग जोड़ना. अगर आपका नेटिव यूज़र इंटरफ़ेस (यूआई), WindowInsets के आधार पर किसी कंटेनर में पैडिंग लागू करता है, तो आपको इन इनसेट को वेबव्यू तक पहुंचने से पहले सही तरीके से मैनेज करना होगा. इससे डबल-पैडिंग से बचा जा सकेगा.
डबल-पैडिंग की समस्या तब होती है, जब नेटिव लेआउट और वेब कॉन्टेंट, दोनों में एक जैसे इनसेट डाइमेंशन लागू होते हैं. इससे ज़रूरत से ज़्यादा स्पेस दिखता है. उदाहरण के लिए, मान लें कि एक फ़ोन में 40 पिक्सल का स्टेटस बार है. नेटिव व्यू और वेबव्यू, दोनों में 40 पिक्सल का इनसेट दिखता है. दोनों में 40 पिक्सल की पैडिंग जोड़ी जाती है. इस वजह से, उपयोगकर्ता को सबसे ऊपर 80 पिक्सल का गैप दिखता है.
ज़ीरोइंग का तरीका
डबल-पैडिंग से बचने के लिए, आपको यह पक्का करना होगा कि नेटिव व्यू में पैडिंग के लिए इनसेट डाइमेंशन का इस्तेमाल करने के बाद, उस डाइमेंशन को शून्य पर रीसेट किया जाए. इसके लिए, बदले गए ऑब्जेक्ट को व्यू हैरारकी (व्यू और व्यू ग्रुप के लेआउट का क्रम) से WebView में भेजने से पहले, नए WindowInsets ऑब्जेक्ट पर Insets.NONE का इस्तेमाल करें.
पैरंट व्यू में पैडिंग लागू करते समय, आम तौर पर आपको WindowInsetsCompat.CONSUMED के बजाय Insets.NONE सेट करके, ज़ीरोइंग अप्रोच का इस्तेमाल करना चाहिए.
कुछ मामलों में, WindowInsetsCompat.CONSUMED को वापस लाने से काम बन सकता है.
हालांकि, अगर आपके ऐप्लिकेशन का हैंडलर, इनसेट में बदलाव करता है या अपनी पैडिंग जोड़ता है, तो इसमें समस्याएं आ सकती हैं. ज़ीरोइंग की रणनीति में ये सीमाएं नहीं होती हैं.
इन्सेट को शून्य करके, घोस्ट पैडिंग से बचना
अगर ऐप्लिकेशन ने पहले इस्तेमाल नहीं किए गए इनसेट पास किए हैं और आपने उन्हें इस्तेमाल किया है या इनसेट में बदलाव होता है (जैसे, कीबोर्ड छिप जाता है), तो उन्हें इस्तेमाल करने से WebView को ज़रूरी अपडेट की सूचना नहीं मिलती. इसकी वजह से, WebView पिछली स्थिति से घोस्ट पैडिंग को बनाए रख सकता है. उदाहरण के लिए, कीबोर्ड छिपाने के बाद भी कीबोर्ड पैडिंग को बनाए रखना.
यहां दिए गए उदाहरण में, ऐप्लिकेशन और WebView के बीच काम न करने वाले इंटरैक्शन को दिखाया गया है:
- शुरुआती स्थिति: ऐप्लिकेशन, शुरुआत में WebView को इस्तेमाल न किए गए इनसेट (उदाहरण के लिए,
displayCutout()याsystemBars()) पास करता है. WebView, वेब कॉन्टेंट पर इंटरनल तौर पर पैडिंग लागू करता है. - स्थिति में बदलाव और गड़बड़ी: अगर ऐप्लिकेशन की स्थिति बदलती है (उदाहरण के लिए, कीबोर्ड छिप जाता है) और ऐप्लिकेशन,
WindowInsetsCompat.CONSUMEDको दिखाकर, इनसेट को मैनेज करने का विकल्प चुनता है. - सूचना ब्लॉक की गई: इनसेट का इस्तेमाल करने से, Android सिस्टम, WebView को व्यू हैरारकी (व्यू और व्यू ग्रुप के लेआउट का क्रम) के ज़रिए ज़रूरी अपडेट की सूचना नहीं भेज पाता.
- घोस्ट पैडिंग: WebView को अपडेट नहीं मिलता है. इसलिए, यह पिछली स्थिति की पैडिंग को बनाए रखता है. इससे घोस्ट पैडिंग होती है. उदाहरण के लिए, कीबोर्ड छिपाने के बाद भी कीबोर्ड की पैडिंग को बनाए रखना.
इसके बजाय, ऑब्जेक्ट को चाइल्ड व्यू में पास करने से पहले, हैंडल किए गए टाइप को शून्य पर सेट करने के लिए, WindowInsetsCompat.Builder का इस्तेमाल करें. इससे WebView को पता चलता है कि व्यू हैरारकी (व्यू और व्यू ग्रुप के लेआउट का क्रम) में सूचना को जारी रखने की सुविधा चालू करते समय, उन खास इनसेट को पहले ही शामिल कर लिया गया है.
Kotlin
ViewCompat.setOnApplyWindowInsetsListener(rootView) { view, windowInsets -> // 1. Identify the inset types you want to handle natively val types = WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.displayCutout() // 2. Extract the dimensions and apply them as padding to the native container val insets = windowInsets.getInsets(types) view.setPadding(insets.left, insets.top, insets.right, insets.bottom) // 3. Return a new WindowInsets object with the handled types set to NONE (zeroed). // This informs the WebView that these areas are already padded, preventing // double-padding while still allowing the WebView to update its internal state. WindowInsetsCompat.Builder(windowInsets) .setInsets(types, Insets.NONE) .build() }
Java
ViewCompat.setOnApplyWindowInsetsListener(rootView, (view, windowInsets) -> { // 1. Identify the inset types you want to handle natively int types = WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.displayCutout(); // 2. Extract the dimensions and apply them as padding to the native container Insets insets = windowInsets.getInsets(types); rootView.setPadding(insets.left, insets.top, insets.right, insets.bottom); // 3. Return a new Insets object with the handled types set to NONE (zeroed). // This informs the WebView that these areas are already padded, preventing // double-padding while still allowing the WebView to update its internal // state. return new WindowInsetsCompat.Builder(windowInsets) .setInsets(types, Insets.NONE) .build(); });
ऑप्ट आउट करने का तरीका
इन आधुनिक तरीकों को बंद करने और लेगसी व्यूपोर्ट हैंडलिंग पर वापस जाने के लिए, यह तरीका अपनाएं:
इनसेट को इंटरसेप्ट करना:
setOnApplyWindowInsetsListenerका इस्तेमाल करें याWebViewसबक्लास मेंonApplyWindowInsetsको बदलें.इनसेट मिटाना: इस्तेमाल किए गए इनसेट का सेट (उदाहरण के लिए,
WindowInsetsCompat.CONSUMED) शुरुआत से वापस करें. इस कार्रवाई से, इनसेट की सूचना को वेबव्यू में पूरी तरह से फैलने से रोका जाता है. इससे, आधुनिक व्यूपोर्ट का साइज़ बदलने की सुविधा बंद हो जाती है. साथ ही, वेबव्यू को अपने शुरुआती विज़ुअल व्यूपोर्ट साइज़ को बनाए रखने के लिए मजबूर किया जाता है.