Android WebView輸入框被檔問題升級解析

前言

之前寫過一篇文章,有講如何處理Android輸入框被軟鍵盤擋住的問題,無論是原生的還是webview的,這裡面主要的問題是webview的問題比較難處理,沒有看過的可以先看看  Android 輸入框被擋問題完美解決方案

主要是issue 5497這個問題。然後可能有些朋友覺得,這篇文章沒能解決他的問題,或者說按照我的代碼去寫又會出現新的問題。這說明沒有能理解這篇文章寫的內容,我隻是舉瞭一個自己碰到的場景,然後去分析,為什麼會這樣,並用一些源碼告訴你為什麼這樣寫的能解決。但是並不是所有的場景去套這個代碼都是正常的,不過如果你理解其中的一些原理的話,你至少能有個方向知道該從何下手去解決你自己碰到的場景。

如果看不懂沒關系,我這次講慢點,再去慢慢分析更多的場景,但是有一點要記住,我對這個問題的處理不是萬金油,你必須要有一定的理解,知道一個方向,再去解決自己碰到的場景,不要直接套代碼。 這裡分析的問題就是issue 5497這個問題。

issue 5497問題

我們再簡單回顧一下這個問題,原生的軟鍵盤和輸入框的沖突,直接設置window的softInputMode就能解決,這個很簡單。但是如果輸入框是webview內部H5的輸入框的情況下pan會失效,隻能用resize。並且,如果是這個window是概念上全屏的情況下(設置全屏的方式很多),resize也會失效。

我上一篇文章中,我碰到的問題的場景是: 一個Dialog,裡面的根頁面設置瞭沉浸模式,根佈局下有一個webview,webview中有個輸入框,點擊輸入框時彈出軟鍵盤會擋住輸入框。

我們先分析,為什麼會擋住輸入框?因為默認的softInputMode在正常情況下會頂起輸入框,但是webview會失效,那我們就把softInputMode設成SOFT_INPUT_ADJUST_RESIZE

然後發現沒效果,為什麼沒效果?因為我的Dialog是全屏的,並且設置瞭沉浸模式,所以符合瞭全屏情況下resize也會失效這個條件。註意這個全屏可以理解成指的是概念上的全屏,不是我們視覺效果上的全屏,也就是這時去設置marginTop,通過這些方法去改變視覺上不是全屏是不會有效果的。

我們的思路就是破解讓這個window變成非全屏。 從上一篇文章可以看出,我們用的方法是設置fitSystemWindows,通過fitSystemWindows設置為true,來破解沉浸模式導致的全屏效果,原理是什麼?通過上一篇文章知道,原理是設置一個安全距離,但是這個安全距離會導致你的window被壓縮,所以我們要重寫view的fitSystemWindows方法設置安全距離去防止window被壓縮

@Override
protected boolean fitSystemWindows(Rect insets) {
    insets.top = 0;
    return super.fitSystemWindows(insets);
}

而這個問題的解決思路是通過設置fitSystemWindows去打破全屏這個條件,從而使SOFT_INPUT_ADJUST_RESIZE能對webview生效。 這是重點的一步,後續的操作都是為瞭處理fitSystemWindows所帶來的影響。

佈局頂起後距離軟鍵盤有一定距離

一般我們的佈局頂起後底部也是緊貼軟鍵盤,有的朋友可能會說,為什麼我也這樣做瞭,但是我webview佈局被軟鍵盤頂起之後距離軟鍵盤會存在一部分的間距。

如果你不知道這個問題,說明對softInputMode不太理解,雖然我個人對這個理解也不是很深,但是如果你能使用SOFT_INPUT_ADJUST_PAN的話,就一定不會出現這個問題,但是用SOFT_INPUT_ADJUST_RESIZE的話,就會在某些佈局中有這個問題,可惜上面說瞭,webview對SOFT_INPUT_ADJUST_PAN無效。

這是為什麼呢?因為簡單來說SOFT_INPUT_ADJUST_PAN是頂起你的輸入框,而SOFT_INPUT_ADJUST_RESIZE會把window給頂起來。所以如果你是window全屏並且webview也是全屏的情況就不會遇到這個問題(這裡其實也就高度影響,寬度不影響),但如果你是window中的webview距離window的底部有一定的距離,這時候用SOFT_INPUT_ADJUST_RESIZE頂起來就會和輸入法有一段距離。

那這個問題要如何解決,這個解決的方法很多,比如通過邏輯手段,或者調整webview大小之類的,這個就沒什麼好說的瞭。

Activity的webview輸入框被擋

上一篇文章包括上面有講我在Dialog中的webview的場景的解決方案。有的朋友會說我activity的webview也是這樣的,但是按照你這個代碼寫進去沒有效果,我明明也給window設置瞭SOFT_INPUT_ADJUST_RESIZE,也給view設置瞭setFitsSystemWindows,也重寫瞭fitSystemWindows方法設置top,但是沒效果。

這就說明你還沒明白為什麼會出現這個問題,你隻是希望隨便去找個文章拷代碼下來用,代碼有用就覺得這個作者牛,代碼沒效果就覺得這個作者傻。好,哪怕你是不看為什麼,隻想考代碼,套到你使用的地方沒效果,那為何不問問為什麼沒效果,你可以在評論區留言,說你是什麼樣的場景,使用這個代碼沒效果。寫一兩句留言對你來說也並不耗多少時間,我隻是覺得,解決問題,需要知道一個方向,不能一味的隻想抄答案,這樣去解決問題是很耗費時間的,而且這樣解決問題也可能會出現其它的問題。

有點扯遠瞭,話說回來,為什麼上面的代碼對Activity可能沒效果。如果認真看都知道,我說瞭造成SOFT_INPUT_ADJUST_RESIZE失效的原因是全屏,而我上面Dialog的場景,造成全屏的操作是設置瞭沉浸模式,所以setFitsSystemWindows是為瞭處理沉浸模式導致全屏的情況。而你的Activity的全屏,不一定是沉浸模式造成的,所以你使用setFitsSystemWindows會無效。

還看不懂沒關系,再舉個例子。你給你的activity設置Fullscreen的主題theme也會導致全屏,這時候給window設置SOFT_INPUT_ADJUST_RESIZE無效,我們的思路是如何去破解Fullscreen這個主題造成的全屏。我們可以動態去概念theme,行不行?當然可以,但是這個時機要寫對。

我們也可以用window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)去破解全屏的效果嘛。但是這個clearFlags如果對你的需求造成瞭影響,你還要通過其它方法去消除這個影響,這種就具體分析具體解決瞭,沒有標準的答案。

總結

寫這篇文章主要是想說明,這個webview被輸入法擋住的問題,這個issue 5497,是一個比較麻煩的問題,它不是光靠隨便在網上去抄個代碼就能解決的。包括你可能會去通過監聽輸入法的彈出去計算滾動的高度,這種方法理論上是不難,實際去開發也是要做一些細節處理和兼容的。

這篇文章沒有貼多少代碼,主要講一個解決問題的思路。要去理解這個問題是為什麼發生的,知道一個方向,才能去更好的解決問題,你可以不按照我的代碼去寫,但是你知道解決問題的方向後,你甚至能自己通過適合自己業務的邏輯代碼去解決你的問題。

我不保證我對整個問題的理解是完全正確的,但是如果有大佬覺得我的理解有問題,可以指出,我也希望能這樣,這樣反而讓我印象更深刻。但是如果有人想不瞭解這些內容的情況下通過去找別人的代碼去碰運氣來解決問題,那我也隻能祝你好運。

以上就是Android WebView輸入框被檔問題升級解析的詳細內容,更多關於Android WebView輸入框的資料請關註WalkonNet其它相關文章!

推薦閱讀: