Thread
#compose
    m

    MaxUt

    1 year ago
    Hi there, I'm trying to maintain the navigation and scrollstate of a WebView but haven't manage to make it work so far. I decided to hoist the webView and webViewClient to the parent composable but when switching tab, the webview doesn't seem to come back to its previous state. Any idea what would cause such problem ?
    Filip Wiesner

    Filip Wiesner

    1 year ago
    m

    MaxUt

    1 year ago
    My bad 🙂
    @Composable
    fun ParentComposable() {
        var webView by rememberSaveable { mutableStateOf<WebView?>(null) }
        var webViewClient by rememberSaveable { mutableStateOf<WebViewClient?>(null) }
    
        Scaffold(
            ...
        ) {
            ChildComposable(
                urlToRender = AppConfig.url,
                webView = webView,
                onWebViewInit = onWebViewInit = { webView = it },
                webViewClient = webViewClient,
                onWebViewClientInit = { webViewClient = it },
            )
        }
    }
    
    
    @Composable
    fun ChildComposable(urlToRender: String, webView: WebView?, onWebViewInit: (WebView) -> Unit, webViewClient: WebViewClient?, onWebViewClientInit: (WebViewClient) -> Unit) {
        val client = object : WebViewClient() {
            override fun onPageFinished(view: WebView, url: String) {
                loadJs()
            }
        }
        AndroidView({ context ->
            WebView(context).apply{
                layoutParams = ViewGroup.LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.MATCH_PARENT
                )
                settings.domStorageEnabled = true
                settings.javaScriptEnabled = true
            }.also { onWebViewInit(it) }
        })
        DisposableEffect(webView, urlToRender) {
            onWebViewClientInit(client)
            webView?.webViewClient = webViewClient!!
            webView?.loadUrl(urlToRender)
            onDispose {
                webView?.stopLoading()
            }
        }
    }
    j

    julioromano

    1 year ago
    AFAIK WebView doesn’t save/restore scroll position even with the “old” View system. Only way I could ever get around this is to somehow keep the instance of the WebView object alive (i.e. don’t let it be garbage collected and then recreated).
    m

    MaxUt

    1 year ago
    Thanks @julioromano. How would you recommend to do so ? I've done some test storing the webView in a Singleton but it doesn't seem to work.
    if (TestSingleton.webView === null) {
            AndroidView({ context ->
                WebView(context).apply{
                    layoutParams = ViewGroup.LayoutParams(
                        ViewGroup.LayoutParams.MATCH_PARENT,
                        ViewGroup.LayoutParams.MATCH_PARENT
                    )
                    settings.domStorageEnabled = true
                    settings.javaScriptEnabled = true
                    webViewClient = client
                }.also { TestSingleton.webView = it }
            })
        }
    
        DisposableEffect(TestSingleton.webView, urlToRender) {
            TestSingleton.webView?.loadUrl(urlToRender)
            onDispose {
                TestSingleton.webView?.stopLoading()
            }
        }
    j

    julioromano

    1 year ago
    I’ve done something similar with the View system in the past but not with Compose. I used to keep the WebView instance inside a ViewModel. However your code looks incomplete: what if
    (TestSingleton.webView != null)
    ? In that case when the AndroidView is created you should pass in the WebView instance previously saved in the singleton.
    m

    MaxUt

    1 year ago
    Great, I'll check that out, thanks a lot 🙂
    Zach Klippenstein (he/him) [MOD]

    Zach Klippenstein (he/him) [MOD]

    9 months ago
    FWIW I filed an feature request to make this easier to do if you wanna star it: https://issuetracker.google.com/208439888