Search code examples
androidwebviewandroid-webview

WebView on Chinese devices ignores forcely set view size


I have a WebView, that adapts to its content height:

        with(this.settings) {
            javaScriptEnabled = true
            allowFileAccess = true
            displayZoomControls = false
            builtInZoomControls = false
            cacheMode = WebSettings.LOAD_NO_CACHE
            layoutAlgorithm = WebSettings.LayoutAlgorithm.NORMAL // Tried the default one
            setSupportZoom(false)
        }
        isVerticalScrollBarEnabled = false
        isHorizontalScrollBarEnabled = false
        setBackgroundColor(Color.TRANSPARENT)
        setLayerType(View.LAYER_TYPE_HARDWARE, null)
        setWebViewClient(webViewClient)
        clearCache(true)


        addJavascriptInterface(this, "MathView")
    private val webViewClient = object : WebViewClient() {

        override fun onPageFinished(view: WebView?, url: String?) {
            super.onPageFinished(view, url)

            Timber.d("onPageFinished: $url")

            invalidate()

            loadUrl("javascript:MathView.resize(document.body.scrollHeight)")
        }

        override fun onPageCommitVisible(view: WebView?, url: String?) {
            super.onPageCommitVisible(view, url)
            // skip code
            invalidate()
        }
    }

When the page loads, I call JS code with callback to find out content height:

@JavascriptInterface
    fun resize(newContentHeight: Float) {
        runOnMain {
            val calculatedHeight = (newContentHeight * resources.displayMetrics.density).toInt()
            val webViewContentHeight = (this.contentHeight * resources.displayMetrics.density).toInt()

            Timber.d("Content height changed: $newContentHeight for content $htmlBody")
            Timber.d("Calculated height: $calculatedHeight; current height: $height; webview content height: $webViewContentHeight")

            if (calculatedHeight != lastCalculatedHeight) {
                lastCalculatedHeight = calculatedHeight

                Timber.d("Setting new height: $calculatedHeight")

                updateLayoutParams {
                    height = lastCalculatedHeight
                    requestLayout()
                    invalidate()
                }
            }
        }
    }

// I also call this code once a second in the debug version to check the sizes.

On most devices it works fine:

Calculated height: 252; current height: 252; webview content height: 252
  • Calculated height — content height reported by JS multiplied by screen density
  • Current height — WebView (as an Android view) height
  • webview content height — content height reported by the WebView itself

As you can see, all values are equal, and that's correct.

But on the different Chinese devices (Xiaomi MiA1 Android 9, Lenovo P1a42 Android 6.0.1) it ignores layout updates and sets different view height:

// Note: this is different content then above, so calculated height is not equal to the above one

Calculated height: 315; current height: 567; webview content height: 567
  • Calculated heught reported by the JS is correct
  • Current height and webview content height are not correct and they are not changed by the layout params update.

How to fix this problem?


Solution

  • Okay, it's a bug across lots of different Chinese devices, at least Xiaomi and Lenovo, starting from Android 6.0 to Android 10 (Android 5.0-5.1 is OK).

    Seems that they copy-pasted the same incorrect code to their firmwares.