Android get height of webview content once rendered

后端 未结 5 1408
忘了有多久
忘了有多久 2020-12-14 18:44

I\'m trying to get the height of a webview once it has been rendered. It always returns null, I\'ve tried getHeight, getMeasuredHeight, getCo

相关标签:
5条回答
  • 2020-12-14 19:06

    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
                    }
                }
            }

    0 讨论(0)
  • 2020-12-14 19:14

    You can use ViewTreeObserver on that WebView to get actual height after rendering its content.

    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;
                       }
               });
    
    0 讨论(0)
  • 2020-12-14 19:20

    I found this solution to be 100% reliable.

    Subclass your WebView and there is a need to invoke javascript after the content has been loaded.

    // 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):

    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!

    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()
    
    0 讨论(0)
  • 2020-12-14 19:26

    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

    0 讨论(0)
  • 2020-12-14 19:29

    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

    The last one is correct.
    ViewTreeObserver sometimes gave me the wrong height.

    0 讨论(0)
提交回复
热议问题