1. 程式人生 > >android ScollView 巢狀 WebView 底部空白,高度無法自適應解決

android ScollView 巢狀 WebView 底部空白,高度無法自適應解決

對技術感興趣的同鞋加群 544645972 一起交流。
最近要做一個頁面,需要 ScrollView 巢狀 WebView,怎麼巢狀,怎麼解決焦點和 touch 事件衝突,網上一大堆,這裡就不贅述了,但是發現 WebView 從一個高度很高的網頁載入一個高度很低的網頁的時候,高度無法自適應了,造成底部會有一大片的空白,解決方案找到了挺多,描述一下:

Google 官方建議

  Google 建議不要在 ScrollView 中使用 WebView,但是畢竟無法避免,產品的需求;

移除重新新增新的 WebView

  每次載入新的 url 的時候 remove 掉舊的 WebView,重新加入一個新的 WebView 去載入這個新的 url,這種方案是可行的,但是畢竟不太好,效率不高,而且會造成體驗上不太好;

JS 注入,獲取頁面內容高度,設定成 WebView 高度

  JS 注入,通過前端 JS 呼叫 native 方法,把高度值傳遞過來,然後通過 layoutparams 去設定 webview 的高度:

mWebView.setWebViewClient(new WebViewClient() {
    @Override
    public void onPageFinished(WebView view, String url) {
        mWebView.loadUrl("javascript:App.resize(document.body.getBoundingClientRect().height)"
); super.onPageFinished(view, url); } }); mWebView.addJavascriptInterface(this, "App");
@JavascriptInterface
public void resize(final float height) {
    getActivity().runOnUiThread(new Runnable() {
        @Override
        public void run() {
            //Toast.makeText(getActivity(), height + "", Toast.LENGTH_LONG).show();
//此處的 layoutParmas 需要根據父控制元件型別進行區分,這裡為了簡單就不這麼做了 mWebView.setLayoutParams(new LinearLayout.LayoutParams(getResources().getDisplayMetrics().widthPixels, (int) (height * getResources().getDisplayMetrics().density))); } }); }

需要注意的是上面的 resize 方法一定要上面那麼寫,寫成:

mWebView.getLayoutParams().height = (int) (height * getResources().getDisplayMetrics().density);

這樣是無法成功的,看來寬度也是有影響的

感謝 @imesong 同學,這段程式碼有亮點可以完善的地方:

  1. mWebVew.setLayoutParam() 時,應該根據 WebView 父控制元件的型別,建立 LayoutParam,或者直接用 mWebView.getLayoutParams() 獲取 LayoutParams;
  2. 呼叫 JAVA 方法的 JS ,可以在網頁載入完成時自己載入下面這段 JS 程式碼(區別在於一個是終端處理,一個是前段處理),比如:
(function(w){
    window.App.resize(document.body.getBoundingClientRect().height);
})(window); 

載入這段 JS 就可以了,“APP” 和上面一樣是自己註冊是自己註冊的介面名字;
思路是一樣的,處理方式有差異。

試驗不太成功的方式

  網上也找到了一些其他的方式,試了一下,不太成功,不知道是不是使用姿勢的問題,感興趣的也可以試試,反饋結果給我。

先載入一個空網頁

  在從高網頁載入低網頁的時候,先載入一個空內容,接著立馬做相關的處理操作(比如載入新的網頁,更改字型等),

// load empty data to shrink the WebView instance
mArticleWebView.loadUrl(Constants.ASSETS_EMPTY);
// load real data
mArticleWebView.loadDataWithBaseURL(null,data,"text/html","utf-8",null);

Constants.ASSETS_EMPTY 僅僅只是一個 String 子串,標識該空網頁的位置,所以該變數可以為 “file:///android_asset/Empty.html”.
試了一下,也是不好用的,不知道是不是我的操作問題,
原文連結 http://vision-apps.blogspot.hk/2012/08/android-webview-tips-tricks.html

修改 Setting 屬性

wv.getSettings().setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
wv.setVerticalScrollBarEnabled(false);
wv.setVerticalScrollbarOverlay(false);
wv.setHorizontalScrollBarEnabled(false);
wv.setHorizontalScrollbarOverlay(false);

另外一些人的討論

總結

  綜合考慮來看,第三種方式是比較合適的,我當時也是使用的第三種方式解決的這個問題。