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 同學,這段程式碼有亮點可以完善的地方:
- mWebVew.setLayoutParam() 時,應該根據 WebView 父控制元件的型別,建立 LayoutParam,或者直接用 mWebView.getLayoutParams() 獲取 LayoutParams;
- 呼叫 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);
另外一些人的討論
總結
綜合考慮來看,第三種方式是比較合適的,我當時也是使用的第三種方式解決的這個問題。