WebView在NestedScrollView中高度不稳定¶
WebView在NestedScrollView中高度不稳定,首次加载后,webView底部会有一大块空白区域。
本文中使用的是com.tencent.smtt.sdk.WebView
layout层级如下。NestedScrollView包着一个LinearLayout,然后再包着WebView。
<androidx.core.widget.NestedScrollView
android:id="@+id/fisher_nest"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!-- 其他view -->
<com.tencent.smtt.sdk.WebView
android:id="@+id/fisher_web"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/transparent" />
<!-- 其他view -->
</LinearLayout>
</androidx.core.widget.NestedScrollView>
加载的是html文本数据,使用的加载方式如下
首次加载后会发现webView底部有一大块空白。假设文本需要的高度是1000px,但实际展示高度是4000px。 而替换html内容再次加载后,webView高度会变矮一些。
为了规避这个问题,我们采用加载空文本 + 动态测量高度的方式。
预加载空文本¶
wv
是WebView。
在加载目标文本之前,先加载一个中间信息。然后延时显示目标文本。
// 先显示点其他的信息
wv.loadDataWithBaseURL(null, "<html><body><div id='whole'>welcome to an.rustfisher.com</div></body></html>",
"text/html", "UTF-8", null);
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
// 显示目标文本
}
}, 700);
js接口¶
html文本中,给内容最外层包上一个<div>
,并打上标示。
例如
新建监听器JSActionListener
。定义方法onResize(float height)
。
新建JSAction
类,里面增加js接口方法,需要使用@JavascriptInterface
注解。
public class JSAction {
public static final String JS_INTERFACE_NAME = "android"; // 提供给js
private JSActionListener listener;
private Handler mHandler = new Handler(Looper.getMainLooper());
public JSAction(JSActionListener listener) {
this.listener = listener;
}
@JavascriptInterface
public void resize(final float height) {
mHandler.post(new Runnable() {
@Override
public void run() {
listener.onResize(height);
}
});
}
}
js接口名称是resize
,后面要用js来调用它。
配置WebView¶
分为2步。首先把前面定义好的接口用起来。js要和Java进行沟通。
webView需要允许js方法。setJavaScriptEnabled
已经deprecated,但这里为了方便继续使用。
添加js接口¶
WebSettings webSettings = wv.getSettings();
webSettings.setJavaScriptEnabled(true);
wv.addJavascriptInterface(new JSAction(new JSActionListener() {
@Override
public void onResize(final float height) {
super.onResize(height);
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) wv.getLayoutParams();
lp.height = (int) (height * getResources().getDisplayMetrics().density);
wv.setLayoutParams(lp);
}
}), JSAction.JS_INTERFACE_NAME);
页面加载完成¶
监听到页面加载完毕后,让webView去调用js方法。
- android就是前面定义的
JSAction.JS_INTERFACE_NAME
。 document.getElementById(\"whole\").offsetHeight
能拿到id为whole
的元素的高度。- 这里不定义id应该也可以,直接用
document.body.getBoundingClientRect()
应该也行。
- 这里不定义id应该也可以,直接用
wv.setWebViewClient(new WebViewClient() {
@Override
public void onPageFinished(WebView view, String url) {
wv.loadUrl("javascript:android.resize(document.getElementById(\"whole\").offsetHeight)");
super.onPageFinished(view, url);
}
});
运行表现是,先显示welcome to an.rustfisher.com
字样,然后再显示目标文本数据。
更进一步的做法是,在onPageFinished
监听到中间数据显示完毕后,再去加载目标数据。
本站说明
一起在知识的海洋里呛水吧。广告内容与本站无关。如果喜欢本站内容,欢迎投喂作者,谢谢支持服务器。如有疑问和建议,欢迎在下方评论~