androidkotlinandroid-webviewandroid-jetpack-composeonbackpressed

Jetpack Compose WebView Handling Back Navigation And Go To Previous Page


I am using Jetpack Compose and have a WebView wrapped in a AndroidView composable that looks like the following:

AndroidView(modifier = modifier, factory = { context ->
        WebView(context).apply {
            layoutParams = ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT
            )
            webViewClient = WebViewClient()
            settings.javaScriptEnabled = true
        }
    }, update = { webView -> webView.loadUrl(url) })

In the legacy way, we could add a OnBackPressedDispatcher to the Activity to intercept the back press and navigate inside the WebView by accessing it via viewBinding for example with functions of the WebView like goBack() and to check if you can go back with canGoBack().

But how can we achieve the same with this Jetpack Compose approach?


Solution

  • There doesn't seem to be anything wrong with assigning the WebView to an external var so that's what I've done here.

    var backEnabled by remember { mutableStateOf(false) }
    var webView: WebView? = null
    AndroidView(
        modifier = modifier,
        factory = { context ->
            WebView(context).apply {
                layoutParams = ViewGroup.LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.MATCH_PARENT
                )
                webViewClient = object : WebViewClient() {
                    override fun onPageStarted(view: WebView, url: String?, favicon: Bitmap?) {
                        backEnabled = view.canGoBack()
                    }
                }
                settings.javaScriptEnabled = true
    
                loadUrl(url)
                webView = this
            }
        }, update = {
            webView = it
        })
    
    BackHandler(enabled = backEnabled) {
        webView?.goBack()
    }
    

    The WebViewClient listens for onPageStarted which checks if the WebView can navigate backwards and then updates backEnabled. This causes a recomposition which toggles the BackHandler on and off.

    I've also moved loadUrl out of the update function and into factory because update is called every time there's a recomposition whereas factory is only called the once. This may or may not be relevant based on your implementation.