WebView, कॉन्टेंट अलाइनमेंट को मैनेज करने के लिए दो व्यूपोर्ट का इस्तेमाल करता है: लेआउट व्यूपोर्ट (पेज का साइज़) और विज़ुअल व्यूपोर्ट (पेज का वह हिस्सा जो उपयोगकर्ता को दिखता है). लेआउट व्यूपोर्ट आम तौर पर स्टैटिक होता है. हालांकि, जब उपयोगकर्ता ज़ूम करते हैं, स्क्रोल करते हैं या जब सिस्टम यूज़र इंटरफ़ेस (यूआई) एलिमेंट (जैसे कि सॉफ़्टवेयर कीबोर्ड) दिखते हैं, तो विज़ुअल व्यूपोर्ट डाइनैमिक रूप से बदलता है.
सुविधा के साथ काम करने की क्षमता
विंडो इंसर्ट के लिए वेबव्यू की सुविधा समय के साथ बेहतर हुई है, ताकि वेब कॉन्टेंट का व्यवहार, नेटिव Android ऐप्लिकेशन की उम्मीदों के मुताबिक हो:
| Milestone | सुविधा जोड़ी गई | दायरा |
|---|---|---|
| M136 | displayCutout() और systemBars() के लिए, सीएसएस सेफ़-एरिया-इनसेट की मदद से सहायता मिलती है. |
सिर्फ़ फ़ुलस्क्रीन WebViews. |
| M139 | ime() (इनपुट मेथड एडिटर, जो एक कीबोर्ड है) के लिए, विज़ुअल व्यूपोर्ट का साइज़ बदलने की सुविधा उपलब्ध है. |
सभी वेबव्यू. |
| M144 | displayCutout() और systemBars() के साथ काम करता है. |
सभी वेबव्यू (फ़ुलस्क्रीन मोड में होने पर भी). |
ज़्यादा जानकारी के लिए, WindowInsetsCompat देखें.
मुख्य मकैनिक
WebView, इनसेट को दो मुख्य तरीकों से मैनेज करता है:
सेफ़ एरिया (
displayCutout,systemBars): WebView, CSS safe-area-inset-* वैरिएबल के ज़रिए इन डाइमेंशन को वेब कॉन्टेंट पर फ़ॉरवर्ड करता है. इससे डेवलपर, अपने इंटरैक्टिव एलिमेंट (जैसे, नेविगेशन बार) को नॉच या स्टेटस बार से छिपाने से रोक सकते हैं.इनपुट के तरीके के एडिटर (आईएमई) का इस्तेमाल करके विज़ुअल व्यूपोर्ट का साइज़ बदलना: M139 से, इनपुट के तरीके का एडिटर (आईएमई) सीधे तौर पर विज़ुअल व्यूपोर्ट का साइज़ बदलता है. आकार बदलने का यह तरीका, WebView-Window के इंटरसेक्शन पर भी आधारित होता है. उदाहरण के लिए, Android के मल्टीटास्किंग मोड में, अगर किसी WebView का निचला हिस्सा विंडो के निचले हिस्से से 200 डीपी नीचे तक फैला हुआ है, तो विज़ुअल व्यूपोर्ट, WebView के साइज़ से 200 डीपी छोटा होगा. यह विज़ुअल व्यूपोर्ट का साइज़ बदलने की सुविधा, IME और WebView-Window इंटरसेक्शन, दोनों के लिए है. यह सिर्फ़ WebView के सबसे नीचे वाले हिस्से पर लागू होती है. इस सुविधा की मदद से, बाईं, दाईं या ऊपर की ओर ओवरलैप होने पर, साइज़ नहीं बदला जा सकता. इसका मतलब है कि उन किनारों पर दिखने वाले डॉक किए गए कीबोर्ड, विज़ुअल व्यूपोर्ट के साइज़ में बदलाव को ट्रिगर नहीं करते.
इससे पहले, विज़ुअल व्यूपोर्ट का साइज़ नहीं बदलता था. इस वजह से, इनपुट फ़ील्ड अक्सर कीबोर्ड के पीछे छिप जाते थे. व्यूपोर्ट का साइज़ बदलने पर, पेज का दिखने वाला हिस्सा डिफ़ॉल्ट रूप से स्क्रोल किया जा सकता है. इससे यह पक्का होता है कि उपयोगकर्ता, छिपे हुए कॉन्टेंट तक पहुंच सकें.
बाउंड और ओवरलैप लॉजिक
WebView को नॉन-ज़ीरो इंसर्ट वैल्यू सिर्फ़ तब मिलनी चाहिए, जब सिस्टम यूज़र इंटरफ़ेस (यूआई) एलिमेंट (बार, डिसप्ले कटआउट या कीबोर्ड) सीधे तौर पर WebView की स्क्रीन बाउंड्री के साथ ओवरलैप करते हों. अगर कोई वेबव्यू, यूज़र इंटरफ़ेस (यूआई) के इन एलिमेंट के साथ ओवरलैप नहीं होता है (जैसे कि अगर कोई वेबव्यू स्क्रीन के बीच में है और सिस्टम बार को नहीं छूता है), तो उसे इनसेट के तौर पर शून्य मिलना चाहिए.
डिफ़ॉल्ट लॉजिक को बदलने और वेब कॉन्टेंट को पूरे सिस्टम डाइमेंशन देने के लिए, setOnApplyWindowInsetsListener तरीके का इस्तेमाल करें. इससे कोई फ़र्क़ नहीं पड़ता कि कॉन्टेंट ओवरलैप हो रहा है या नहीं. साथ ही, लिसनर से ओरिजनल और बिना बदलाव वाला windowInsets ऑब्जेक्ट वापस पाएं. सिस्टम के सभी डाइमेंशन देने से, डिज़ाइन को एक जैसा बनाए रखने में मदद मिल सकती है. ऐसा इसलिए, क्योंकि इससे वेब कॉन्टेंट को डिवाइस के हार्डवेयर के साथ अलाइन किया जा सकता है. भले ही, WebView की मौजूदा जगह कुछ भी हो. इससे यह पक्का होता है कि 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 के आधार पर किसी कंटेनर में पैडिंग लागू करता है, तो आपको इन इनसेट को WebView तक पहुंचने से पहले सही तरीके से मैनेज करना होगा, ताकि डबल-पैडिंग से बचा जा सके.
डबल-पैडिंग ऐसी स्थिति होती है जब नेटिव लेआउट और वेब कॉन्टेंट, एक जैसे इंसर्ट डाइमेंशन लागू करते हैं. इससे स्पेसिंग ज़रूरत से ज़्यादा हो जाती है. उदाहरण के लिए, मान लें कि किसी फ़ोन में स्टेटस बार 40 पिक्सल का है. नेटिव व्यू और वेबव्यू, दोनों में 40 पिक्सल का इंसर्ट दिखता है. दोनों में 40 पिक्सल की पैडिंग जोड़ी जाती है. इससे उपयोगकर्ता को सबसे ऊपर 80 पिक्सल का अंतर दिखता है.
ज़ीरोइंग का तरीका
डबल-पैडिंग से बचने के लिए, आपको यह पक्का करना होगा कि नेटिव व्यू में पैडिंग के लिए इंसर्ट डाइमेंशन का इस्तेमाल करने के बाद, आपने उस डाइमेंशन को शून्य पर रीसेट कर दिया हो. इसके लिए, नए WindowInsets ऑब्जेक्ट पर Insets.NONE का इस्तेमाल करें. इसके बाद, बदले गए ऑब्जेक्ट को व्यू हैरारकी से WebView पर पास करें.
पैरंट व्यू में पैडिंग लागू करते समय, आपको आम तौर पर WindowInsetsCompat.CONSUMED के बजाय Insets.NONE सेट करके, ज़ीरोइंग अप्रोच का इस्तेमाल करना चाहिए.
WindowInsetsCompat.CONSUMED को वापस लाने की सुविधा, कुछ स्थितियों में काम कर सकती है.
हालांकि, अगर आपके ऐप्लिकेशन का हैंडलर इनसेट बदलता है या अपनी पैडिंग जोड़ता है, तो इसमें समस्याएं आ सकती हैं. ज़िरोइंग के तरीके में ये सीमाएं नहीं होती हैं.
इनसेट को शून्य करके, घोस्ट पैडिंग से बचना
अगर ऐप्लिकेशन ने पहले से ही इस्तेमाल नहीं किए गए इंसर्ट पास किए हैं और आपने उनका इस्तेमाल किया है, तो WebView को ज़रूरी अपडेट की सूचना नहीं मिलेगी. इसके अलावा, अगर इंसर्ट में बदलाव होता है (जैसे कि कीबोर्ड का छिपना), तो भी WebView को ज़रूरी अपडेट की सूचना नहीं मिलेगी. इस वजह से, WebView में पिछली स्थिति से भूतिया पैडिंग बनी रह सकती है. उदाहरण के लिए, कीबोर्ड छिपाने के बाद भी कीबोर्ड पैडिंग बनी रहती है.
यहां दिए गए उदाहरण में, ऐप्लिकेशन और वेबव्यू के बीच इंटरैक्शन में गड़बड़ी दिखाई गई है:
- शुरुआती स्थिति: ऐप्लिकेशन, शुरू में इस्तेमाल नहीं किए गए इनसेट (उदाहरण के लिए,
displayCutout()याsystemBars()) को WebView पर भेजता है. 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();
});
ऑप्ट-आउट करने का तरीका
इन आधुनिक सुविधाओं को बंद करने और लेगसी व्यूपोर्ट हैंडलिंग पर वापस जाने के लिए, यह तरीका अपनाएं:
इंटरसेप्ट इनसेट:
WebViewसबक्लास मेंsetOnApplyWindowInsetsListenerका इस्तेमाल करें याonApplyWindowInsetsको बदलें.क्लियर इंसर्ट: इस्तेमाल किए गए इंसर्ट के सेट (उदाहरण के लिए,
WindowInsetsCompat.CONSUMED) को शुरू से वापस लाएं. इस कार्रवाई से, इंसर्ट की गई सूचना को वेबव्यू में पूरी तरह से फैलने से रोका जाता है. इससे, व्यूपोर्ट के साइज़ को ज़रूरत के हिसाब से बदलने की सुविधा बंद हो जाती है. साथ ही, वेबव्यू को अपने शुरुआती विज़ुअल व्यूपोर्ट के साइज़ को बनाए रखने के लिए मजबूर किया जाता है.