J'essaie d'obtenir le maximum d'une Webview une fois qu'elle a été rendue. Il retourne toujours null, j'ai essayé getHeight
, getMeasuredHeight
, getContentHeight
et il retourne toujours null.
Disposition:
<?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>
Activité
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.");
}
}
}
Je ne sais même pas s'il est possible d'obtenir la hauteur de la vue Web après son rendu, mais je ne vois pas pourquoi vous ne pourriez pas. si quelqu'un avait des solutions, ce serait grandement apprécié.
Vous pouvez utiliser ViewTreeObserver
sur cette WebView
pour obtenir la hauteur réelle après le rendu de son contenu.
voici l'exemple de 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;
}
});
J'ai trouvé cette solution fiable à 100%.
Sous-classez votre WebView et il est nécessaire d'appeler javascript après le chargement du contenu.
// 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)")
}
}
Nous pouvons alors obtenir la bonne hauteur et désactiver javascript dans le rappel (pour des raisons de sécurité et de cohérence):
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 doit appeler post () car le code à l'intérieur de resize (...) est appelé dans le thread WebView!
Ensuite, assurez-vous de mettre à l'échelle vos pixels pour correspondre à la densité des pixels !:
fun formatContentHeight(webView: WebView, height: Int): Int = Math.floor((height * webView.context.resources.displayMetrics.density).toDouble()).toInt()
ok, c'est bien plus tard, mais je pense que c'est une bonne solution, utilisez simplement if (webView.getContentHeight() > 0)
si ture
cela signifie que ça s'est terminé, sinon, ce n'est pas encore fini
Essayé et testé les éléments suivants:
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()
));
}
});
Journaux:
12-20 16: 08: 33.969 1466-1466/yourPkg I/démo: onLayoutChange: top = 0, Bottom = 0, hauteur du contenu = 0
12-20 16: 08: 33.970 1466-1466/yourPkg I/démo: onLayoutChange: top = 0, bottom = 0, hauteur du contenu = 0
12-20 16: 08: 34.061 1466-1466/yourPkg I/demo: onLayoutChange: top = 0, Bottom = 1510, hauteur du contenu = 0
12-20 16: 08: 34.091 1466-1466/yourPkg I/démo: onLayoutChange: top = 0, bottom = 1510, hauteur du contenu = 2050
Le dernier est correct.ViewTreeObserver
m'a parfois donné une mauvaise hauteur.
J'ai choisi cette approche
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
}
}
}