Created
May 22, 2019 11:31
-
-
Save antonis/89fb40abdc5cc2356be7b21afb10a302 to your computer and use it in GitHub Desktop.
Various ways to get the height of a Webview on Android. Nothing really works on all cases
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import android.view.ViewTreeObserver | |
| import android.webkit.JavascriptInterface | |
| import android.webkit.WebView | |
| import android.webkit.WebViewClient | |
| // Try 1 | |
| private fun getHeightFromDocumentBodyScrollHeight(webView: WebView, setHeight: (Int)->Unit) { | |
| webView.webViewClient = object : WebViewClient() { | |
| override fun onPageFinished(view: WebView?, url: String?) { | |
| view?.let { | |
| it.settings.javaScriptEnabled = true | |
| it.addJavascriptInterface(WebAppInterface(it, setHeight), "AndroidGetHeightFunction") | |
| it.loadUrl("javascript:AndroidGetHeightFunction.resize(document.body.scrollHeight)") | |
| } | |
| } | |
| } | |
| } | |
| class WebAppInterface(private val webView: WebView, val setHeight: (Int)->Unit) { | |
| @JavascriptInterface | |
| fun resize(height: Float) { | |
| webView.post { | |
| val h = Math.floor((height * webView.context.resources.displayMetrics.density).toDouble()).toInt() | |
| setHeight(h) | |
| webView.settings.javaScriptEnabled = false | |
| } | |
| } | |
| } | |
| // Try 2 | |
| private 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;})()" | |
| private fun getHeightWithJavascriptEvaluation(webView: WebView, setHeight: (Int)->Unit) { | |
| webView.settings.javaScriptEnabled = true | |
| webView.webViewClient = object : WebViewClient() { | |
| override fun onPageFinished(view: WebView, url: String) { | |
| webView.evaluateJavascript(heightWebViewJSScript) { height -> | |
| val h = Math.floor((height.toInt() * webView.context.resources.displayMetrics.density).toDouble()).toInt() | |
| setHeight(h) | |
| webView.settings.javaScriptEnabled = false | |
| } | |
| } | |
| } | |
| } | |
| // Try 3 | |
| private fun getHeightWithViewTreeObserver(webView: WebView, setHeight: (Int)->Unit) { | |
| webView.viewTreeObserver.addOnPreDrawListener(object : ViewTreeObserver.OnPreDrawListener { | |
| override fun onPreDraw(): Boolean { | |
| val height = webView.measuredHeight | |
| if (height != 0) { | |
| val h = Math.floor((height * webView.context.resources.displayMetrics.density).toDouble()).toInt() | |
| setHeight(height) | |
| webView.viewTreeObserver.removeOnPreDrawListener(this) | |
| } | |
| return false | |
| } | |
| }) | |
| } | |
| // Try 4 | |
| private fun getHeightWithLayoutChangeListener(webView: WebView, setHeight: (Int)->Unit) { | |
| webView.addOnLayoutChangeListener{ _, _, _, _, _, _, _, _, _ -> | |
| setHeight(webView.contentHeight) | |
| } | |
| } |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thank you for reaching out @DhavalsShah :)
Sorry to hear that this is still an issue on Android :(
It's been a while since I've tried this and I don't remember the details. From what I recall in some use cases I was getting erroneous values (eg zero) and retried an alternative approach within the code. Tbh I don't consider the above a solid approach and it's more like a hack.