Java Android 在呈现后获取 webview 内容的高度
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22878069/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Android get height of webview content once rendered
提问by Paddy1990
I'm trying to get the height of a webview once it has been rendered. It always returns null, I've tried getHeight
, getMeasuredHeight
, getContentHeight
and it always returns null.
我试图在渲染后获取 webview 的高度。它总是返回null,我试过getHeight
,getMeasuredHeight
,getContentHeight
它总是返回null。
Layout:
布局:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/instructions"
android:background="@color/transparent_black" >
<WebView
android:id="@+id/top_content"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</RelativeLayout>
Activity
活动
public class TestActivity extends MenuActivity {
private final static String TAG = "HearingTest";
private String urlTopContent;
private WebView topContent;
private boolean mMoreInfoTop = true;
private int mYdelta = 0;
private int mBottomOffset = 0;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.right_hearing_test);
String topHtml = this.getString(R.string.top_content);
//String bottomHtml = this.getString(R.string.bottom_content);
urlTopContent = "file:///android_asset/html/" + topHtml;
WebViewSettings();
LoadWebPage(urlTopContent);
}
public void WebViewSettings(){
topContent = (WebView) findViewById(R.id.top_content);
topContent.getSettings().setJavaScriptEnabled(true);
topContent.getSettings().setBuiltInZoomControls(true);
topContent.getSettings().setSupportZoom(true);
topContent.getSettings().setLoadWithOverviewMode(true);
topContent.setBackgroundColor(0);
topContent.canGoBack();
int topHeight = topContent.getContentHeight();
Log.d("Top Height", "Height: " + topHeight);
topContent.setWebViewClient(new WebViewClient(){
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (Uri.parse(url).getHost().equals(urlTopContent)) {
// This is my web site, so do not override; let my WebView load the page
return false;
}
// Otherwise, the link is not for a page on my site, so launch another Activity that handles URLs
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(intent);
return true;
}
@Override
public void onPageFinished(WebView view, String url) {
View webViewHeight = (View) findViewById(R.id.top_content);
int height = webViewHeight.getHeight();
Log.d("Top Content","Top Content Height:" + height);
}
});
}
public void LoadWebPage(String url){
try {
topContent.loadUrl(url);
Log.d("Loading Web Page", "URL" + url + "connected");
}
catch (Exception e) {
Log.d("Loading Web Page", "URL: " + url + " couldn't connect.");
}
}
}
I don't even know if it's possible to get the height of the web view after it has rendered but I don't see why you couldn't. if anyones got and solutions it would be greatly appreciated.
我什至不知道是否有可能在呈现后获得 web 视图的高度,但我不明白为什么你不能。如果有人得到和解决方案,将不胜感激。
采纳答案by NaserShaikh
You can use ViewTreeObserver
on that WebView
to get actual height after rendering its content.
您可以在渲染其内容后使用ViewTreeObserver
它WebView
来获取实际高度。
here's the sample code.
这是示例代码。
ViewTreeObserver viewTreeObserver = mWebView.getViewTreeObserver();
viewTreeObserver.addOnPreDrawListener(new OnPreDrawListener() {
@Override
public boolean onPreDraw() {
int height = mWebView.getMeasuredHeight();
if( height != 0 ){
Toast.makeText(getActivity(), "height:"+height,Toast.LENGTH_SHORT).show();
mWebView.getViewTreeObserver().removeOnPreDrawListener(this);
}
return false;
}
});
回答by PJ_Finnegan
Tried and tested the following:
尝试并测试了以下内容:
mWebView = new WebView(this);
mWebView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
@Override
public void onLayoutChange(View view, int l, int t, int r, int b, int ol, int ot, int or, int ob) {
Log.i("demo", String.format("%s: top=%d, bottom=%d, content height=%d",
Thread.currentThread().getStackTrace()[2].getMethodName(), t, b, mWebView.getContentHeight()
));
}
});
Logs:
日志:
12-20 16:08:33.969 1466-1466/yourPkg I/demo: onLayoutChange: top=0, bottom=0, content height=0
12-20 16:08:33.970 1466-1466/yourPkg I/demo: onLayoutChange: top=0, bottom=0, content height=0
12-20 16:08:34.061 1466-1466/yourPkg I/demo: onLayoutChange: top=0, bottom=1510, content height=0
12-20 16:08:34.091 1466-1466/yourPkg I/demo: onLayoutChange: top=0, bottom=1510, content height=2050
12-20 16:08:33.969 1466-1466/yourPkg I/demo: onLayoutChange: top=0, bottom=0, content height=0
12-20 16:08:33.970 1466-1466/yourPkg I/demo: onLayoutChange顶部=0,底部=0,内容高度=0
12-20 16:08:34.061 1466-1466/yourPkg I/demo:onLayoutChange:顶部=0,底部=1510,内容高度=0
12-20 16:08: 34.091 1466-1466/yourPkg I/demo:onLayoutChange:顶部=0,底部=1510,内容高度=2050
The last one is correct.ViewTreeObserver
sometimes gave me the wrong height.
最后一个是正确的。ViewTreeObserver
有时给我错误的高度。
回答by Micha? Dobi Dobrzański
I found this solution to be 100% reliable.
我发现这个解决方案是 100% 可靠的。
Subclass your WebView and there is a need to invoke javascriptafter the content has been loaded.
将您的 WebView 子类化,并且需要在加载内容后调用javascript。
// callback made this way in order to get reliable html height and to avoid race conditions
@SuppressLint("SetJavaScriptEnabled")
override fun onPageFinished(view: WebView?, url: String?) {
view?.let {
it.settings.javaScriptEnabled = true
it.addJavascriptInterface(WebAppInterface(it), "AndroidGetHeightFunction")
it.loadUrl("javascript:AndroidGetHeightFunction.resize(document.body.scrollHeight)")
}
}
We can then get proper height and disable javascript in callback(for security and consistency):
然后我们可以获得适当的高度并在回调中禁用 javascript(为了安全和一致性):
inner class WebAppInterface(private val webView: WebView) {
@JavascriptInterface
fun resize(height: Float) {
webView.post {
heightMeasuredListener?.invoke(formatContentHeight(webView, height.toInt()))
webView.settings.javaScriptEnabled = false
}
}
}
WebView must call post()as the code inside resize(...) is called in WebView thread!
WebView必须调用 post()作为 resize(...) 中的代码在 WebView 线程中调用!
After, make sure to scale your pixels to match density pixels!:
之后,确保缩放像素以匹配密度像素!:
fun formatContentHeight(webView: WebView, height: Int): Int = Math.floor((height * webView.context.resources.displayMetrics.density).toDouble()).toInt()
回答by Xianwei
ok, this is pretty later, but I think it nice solution,
just use if (webView.getContentHeight() > 0)
if ture
it means it finsihed, else, it not finished yet
好的,这已经很晚了,但我认为这是一个不错的解决方案,if (webView.getContentHeight() > 0)
如果ture
这意味着它完成了就使用它,否则,它还没有完成
回答by Dmitriy Melekhov
I chose this approach
我选择了这种方法
const val heightWebViewJSScript = "(function() {var pageHeight = 0;function findHighestNode(nodesList) { for (var i = nodesList.length - 1; i >= 0; i--) {if (nodesList[i].scrollHeight && nodesList[i].clientHeight) {var elHeight = Math.max(nodesList[i].scrollHeight, nodesList[i].clientHeight);pageHeight = Math.max(elHeight, pageHeight);}if (nodesList[i].childNodes.length) findHighestNode(nodesList[i].childNodes);}}findHighestNode(document.documentElement.childNodes); return pageHeight;})()"
webView.webViewClient = object : WebViewClient() {
override fun onPageFinished(view: WebView, url: String) {
webView.evaluateJavascript(heightWebViewJSScript
) { height ->
val params = itemView.layoutParams
// params.height
}
}
}