Bailey
Bailey

Reputation: 167

How do you display dark mode webpages in a floating webview in Android

I have an android app where I want to display a webpage in dark mode, overlaid on top of other apps (using android draw over apps facility). I'm using a webview and windowmanager to create the floating view.

I want to target Android 9 / API 28, so that I can use the app with Amazon Fire TV.

The webpage in question is from Home Assistant. Dark mode can be set to auto, dark or light in home assistant. For the purposes of this post, i've set dark mode in the HA settings. When the HA page loads, it shows a "loading data" splash screen before showing the final screen. The issue I am experiencing is that the splash screen is shown light, whereas the final HA screen correctly displays in dark mode.

It has been suggested by the HA team that the splash screen is displayed as light or dark depending upon the browser setting. So, it seems that dark mode needs to be set on the webview.

However, in my test code, I have implemented a test where a webview is used but not floating, it's full screen. In this test, the splash screen is correctly dark. Here are the tests:

Working, but not floating

widget_web.xml

<?xml version="1.0" encoding="utf-8"?>
<WebView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/web_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fadingEdge="vertical"
    android:padding="8dp"
    android:visibility="visible" />

MainActivity.kt

    setContentView(R.layout.widget_web)
    myWebView = findViewById<View>(R.id.web_view) as WebView
    myWebView.settings.javaScriptEnabled = true
    myWebView.setInitialScale(100)
    myWebView.addJavascriptInterface(WebViewJavascriptInterface(applicationContext), "externalApp")
    myWebView.loadUrl("http://192.168.1.73:8123/dashboard-studyonly?external_auth=1")

Splash screen (black, as I need it)

enter image description here

Black Home Assistant page:

enter image description here

Not working, but floating

MainActivity.kt

    lateinit var windowManager: WindowManager
    lateinit var floatView: ViewGroup
    lateinit var mParentView: ViewGroup
    lateinit var floatWindowLayoutParam: WindowManager.LayoutParams

    setContentView(R.layout.widget_web)
    floatWindowLayoutParam = WindowManager.LayoutParams(
        1000,1000,
        WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
        WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
        PixelFormat.TRANSLUCENT
    )

    windowManager = getSystemService(WINDOW_SERVICE) as WindowManager
    val inflater: LayoutInflater =
        baseContext.getSystemService(LAYOUT_INFLATER_SERVICE) as LayoutInflater

    mParentView = FrameLayout(this)
    windowManager.addView(mParentView, floatWindowLayoutParam) //add mParentView to window with assigned parameters
    floatView = inflater.inflate(R.layout.widget_web, null) as ViewGroup //floatView holds the webView
    floatView.visibility = View.GONE
    mParentView.addView(floatView) // add floatView (webView) as child to mParentView
    myWebView = floatView.findViewById(R.id.web_view) as WebView
    myWebView.settings.javaScriptEnabled = true
    myWebView.settings.domStorageEnabled = true
    myWebView.setInitialScale(100)
    myWebView.addJavascriptInterface(WebViewJavascriptInterface(applicationContext), "externalApp")
    myWebView.loadUrl("http://192.168.1.73:8123/dashboard-studyonly?external_auth=1")
    myWebView.requestFocus()
    myWebView.visibility = View.VISIBLE
    finish() // hide the background of the app

Splash screen, white not black:

enter image description here

Black HA theme, as required (but driven by HA settings, not the webview):

enter image description here

Upvotes: 0

Views: 214

Answers (1)

MexiCano
MexiCano

Reputation: 362

Try this

    floatWindowLayoutParam = WindowManager.LayoutParams(
            1000, 1000,
            WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
            WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
            PixelFormat.TRANSLUCENT
        )

        windowManager = getSystemService(WINDOW_SERVICE) as WindowManager
        val inflater: LayoutInflater = getSystemService(LAYOUT_INFLATER_SERVICE) as LayoutInflater

        mParentView = FrameLayout(this)
        windowManager.addView(mParentView, floatWindowLayoutParam)
        
        floatView = inflater.inflate(R.layout.widget_web, mParentView, false) as ViewGroup
        floatView.visibility = View.GONE
        mParentView.addView(floatView) 
        
        myWebView = floatView.findViewById(R.id.web_view) as WebView
        myWebView.settings.javaScriptEnabled = true
        myWebView.settings.domStorageEnabled = true
        myWebView.setInitialScale(100)
        myWebView.addJavascriptInterface(WebViewJavascriptInterface(applicationContext), "externalApp")
        
        myWebView.webViewClient = object : WebViewClient() {
            override fun onPageFinished(view: WebView?, url: String?) {
                super.onPageFinished(view, url)
                injectDarkModeCSS(view)
            }
        }

        myWebView.loadUrl("http://192.168.1.73:8123/dashboard-studyonly?external_auth=1")
        myWebView.requestFocus()
        myWebView.visibility = View.VISIBLE
        finish() 
    }

    private fun injectDarkModeCSS(webView: WebView?) {
        val css = "(function() {" +
                  "document.body.style.backgroundColor = 'black';" +
                  "document.body.style.color = 'white';" +
                  "})()"
        webView?.evaluateJavascript("javascript:$css", null)
    }
}

Upvotes: 1

Related Questions