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

使用Navigation Component时DialogFragment弹出后沉浸式模式导航栏无法隐藏

沉浸式模式下DialogFragment显示/点击时导航栏无法保持隐藏的解决办法

我用Kotlin开发了一款Android原生游戏,现在卡着个问题:沉浸式模式下,通过Navigation Component弹出DialogFragment时,导航栏没法一直隐藏。之前试过网上的方案,但只要点一下DialogFragment的区域,导航栏就会重新弹出来,实在搞不定的话可能只能转Unity开发了。

我的Navigation组件配置(game_graph.xml):

...
<dialog
        android:id="@+id/settingsFragment"
        android:name="nochi.words.ui.SettingsFragment"
        android:label="fragment_settings"
        tools:layout="@layout/fragment_settings" >
</dialog>
...

亲测有效的解决步骤

核心就是让DialogFragment的窗口也强制应用沉浸式规则,同时拦截触摸事件避免系统触发导航栏。

1. 给DialogFragment的窗口设置沉浸式参数

在SettingsFragment里重写onStart(),直接给Dialog的窗口配置:

override fun onStart() {
    super.onStart()
    dialog?.window?.let { window ->
        // 开启粘性沉浸式,隐藏状态栏和导航栏
        window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
                or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                or View.SYSTEM_UI_FLAG_FULLSCREEN
                or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)
        // 让窗口占满整个屏幕,忽略系统栏区域
        window.setFlags(
            WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
            WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
        )
    }
}

2. 拦截触摸事件,防止触发导航栏

如果点击Dialog还是会唤起导航栏,就在onViewCreated()里给根布局加触摸监听,每次触摸时重新应用沉浸式:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    view.rootView.setOnTouchListener { _, event ->
        if (event.action == MotionEvent.ACTION_DOWN) {
            // 触摸时重新设置沉浸式,避免系统弹出导航栏
            dialog?.window?.decorView?.systemUiVisibility = (View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
                    or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                    or View.SYSTEM_UI_FLAG_FULLSCREEN)
        }
        false // 返回false保证子控件能正常响应触摸
    }
}

3. 确保宿主Activity的沉浸式状态稳定

在Activity的onResume()里也重新应用沉浸式,避免Dialog关闭后导航栏异常显示:

override fun onResume() {
    super.onResume()
    window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
            or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
            or View.SYSTEM_UI_FLAG_FULLSCREEN)
}

适配Android 11+的写法

如果你的游戏适配Android 11及以上,建议用新的WindowInsetsController替代旧的systemUiVisibility,兼容性更好:

// 在SettingsFragment的onStart()里替换成这段
dialog?.window?.let { window ->
    val insetsController = window.insetsController ?: return@let
    // 隐藏状态栏和导航栏
    insetsController.hide(WindowInsets.Type.statusBars() or WindowInsets.Type.navigationBars())
    // 设置为滑动时临时显示导航栏,松手后自动隐藏
    insetsController.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 04:31:18