You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Compose WebView返回键优化:避免关闭应用,保留网页回退能力

Compose WebView返回键优化:回退栈为空时避免应用关闭

问题分析

你的代码目前能处理WebView的回退栈,但当回退栈为空时,按下返回键会触发系统默认行为直接关闭应用。核心原因是当前BackHandler仅在backEnabled为true时生效,当WebView无法回退时,BackHandler不拦截返回事件,系统默认的返回逻辑就会关闭Activity。此外,backEnabled仅在onPageStarted中更新,无法实时反映WebView回退栈的变化(比如页面跳转后回退、JS操作历史栈等场景)。

解决方案

调整BackHandler的触发逻辑,让它始终拦截返回事件,然后在回调中实时判断WebView是否具备回退能力:

  1. 将BackHandler的enabled参数设为true,确保始终监听返回键
  2. 在回调中直接通过WebView实例判断canGoBack(),避免依赖可能过期的backEnabled状态
  3. 补充在onPageFinished中更新backEnabled(可选,用于其他依赖该状态的逻辑)

修改后的完整代码

@Composable
fun StatScreen(zeusPrefManager: ZeusPrefManager){

    var fPCallback: ValueCallback<Array<Uri>>? by remember {
        mutableStateOf(null)
    }

    val launcher = rememberLauncherForActivityResult(
        contract = ActivityResultContracts.GetMultipleContents()
    ) {
        fPCallback?.onReceiveValue(it.toTypedArray())
    }

    var backEnabled by remember { mutableStateOf(false) }
    var webView: WebView? = null

    var gameStat by remember {
        mutableStateOf("")
    }

    LaunchedEffect(key1 = "goStat"){
        val destination = zeusPrefManager.zeusStatDataFlow.first()
        gameStat = destination
    }

    if (gameStat != ""){
        AndroidView(factory = { context ->
            WebView(context).apply {
                layoutParams = ViewGroup.LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.MATCH_PARENT
                )
                settings.javaScriptEnabled = true
                settings.domStorageEnabled = true
                settings.loadWithOverviewMode = true
                settings.userAgentString = ZeusConstan.converter007(settings.userAgentString)

                webViewClient = object: WebViewClient(){

                    override fun onPageStarted(view: WebView, url: String?, favicon: Bitmap?) {
                        backEnabled = view.canGoBack()
                    }

                    override fun onPageFinished(view: WebView?, url: String?) {
                        super.onPageFinished(view, url)
                        view?.let {
                            backEnabled = it.canGoBack()
                        }
                    }
                }

                webChromeClient = object : WebChromeClient(){
                    override fun onShowFileChooser(
                        webView: WebView?,
                        filePathCallback: ValueCallback<Array<Uri>>?,
                        fileChooserParams: FileChooserParams?
                    ): Boolean {

                        fPCallback?.onReceiveValue(null)
                        fPCallback = filePathCallback
                        launcher.launch("image/*")
                        return true
                    }
                }
                loadUrl(gameStat)
            }
        }, update = {
            webView = it
        })

        // 始终监听返回键,实时判断WebView状态
        BackHandler(enabled = true) {
            webView?.let { wv ->
                if (wv.canGoBack()) {
                    wv.goBack()
                } else {
                    // 回退栈为空,不执行任何操作,避免应用关闭
                    // 可选:添加用户提示,比如 Toast.makeText(context, "无法继续返回", Toast.LENGTH_SHORT).show()
                }
            }
        }
    }
}

关键修改点

  • BackHandler拦截逻辑:将enabled设为true,确保返回事件始终被拦截,不会触发系统默认的关闭行为
  • 实时状态判断:直接通过webView?.canGoBack()获取当前回退栈状态,避免依赖单一时机更新的backEnabled变量
  • 空安全优化:使用webView?.let避免空指针异常
  • 补充状态更新:在onPageFinished中也更新backEnabled,保证该状态能反映页面加载完成后的回退栈情况

内容的提问来源于stack exchange,提问作者oleg23

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 06:44:58