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

屏幕熄灭或后台恢复后,Fragment导航抽屉无法返回主Fragment

导航状态丢失问题:后台恢复后返回键/汉堡菜单失效

我开发了一个单Activity应用,用Navigation Graph和Navigation Drawer切换Fragment。正常情况下从各Fragment按返回键能回到主Fragment,但屏幕熄灭再点亮或应用进入后台后恢复时,返回按钮变成汉堡菜单,点击没反应,Android返回键也无法导航,就像应用忘了导航路径一样。

原实现代码

导航初始化代码

val navController = (supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment).navController
setSupportActionBar(layoutAppBarMain.layoutToolbarMain)
NavigationUI.setupActionBarWithNavController(this@MainActivity, navController, mainDrawerLayout)
appBarConfiguration = AppBarConfiguration(navController.graph, mainDrawerLayout)
NavigationUI.setupWithNavController(mainActivityNavView, navController)
supportActionBar?.setDisplayShowTitleEnabled(false)

navController.addOnDestinationChangedListener { _: NavController, nd: NavDestination, _: Bundle? ->
    when (nd.id) {
        R.id.playFragment -> mainDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED)
        R.id.navRulesFragment, R.id.navImproveFragment, R.id.navAboutFragment, R.id.navDonateFragment -> mainDrawerLayout.setDrawerLockMode(
            DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
        else -> {
            binding.layoutAppBarMain.layoutToolbarMain.navigationIcon = null
            mainDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
        }
    }
}

导航向上方法重写

override fun onSupportNavigateUp(): Boolean {
    return NavigationUI.navigateUp(navController, appBarConfiguration) || super.onSupportNavigateUp()
}

问题原因

核心问题出在应用后台恢复时,NavController实例可能重新创建,但原有引用未更新,同时AppBarConfiguration与导航栈的关联未同步。另外手动设置navigationIcon = null的操作,在恢复时未重新触发,导致UI状态与实际导航栈不匹配。

修复方案

1. 调整导航初始化逻辑,抽离为单独方法

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = ActivityMainBinding.inflate(layoutInflater)
    setContentView(binding.root)
    
    setupNavigation()
}

private fun setupNavigation() {
    val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
    val navController = navHostFragment.navController
    
    setSupportActionBar(binding.layoutAppBarMain.layoutToolbarMain)
    supportActionBar?.setDisplayShowTitleEnabled(false)
    
    // 明确指定顶层目的地(仅主Fragment显示汉堡菜单)
    appBarConfiguration = AppBarConfiguration(
        setOf(R.id.playFragment),
        binding.mainDrawerLayout
    )
    
    NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration)
    NavigationUI.setupWithNavController(binding.mainActivityNavView, navController)
    
    navController.addOnDestinationChangedListener { _, nd, _ ->
        when (nd.id) {
            R.id.playFragment -> {
                binding.mainDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED)
            }
            R.id.navRulesFragment, R.id.navImproveFragment, R.id.navAboutFragment, R.id.navDonateFragment -> {
                binding.mainDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
            }
            else -> {
                binding.mainDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
            }
        }
    }
}

2. 在onResume中重新同步导航状态

override fun onResume() {
    super.onResume()
    val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
    val navController = navHostFragment.navController
    // 后台恢复后重新关联ActionBar与最新的NavController
    NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration)
}

3. 修改onSupportNavigateUp,实时获取最新NavController

override fun onSupportNavigateUp(): Boolean {
    val navController = (supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment).navController
    return NavigationUI.navigateUp(navController, appBarConfiguration) || super.onSupportNavigateUp()
}

关键修改说明

  • 抽离导航初始化方法,便于重复调用同步状态
  • 明确配置AppBarConfiguration的顶层目的地,让NavigationUI自动管理汉堡/返回图标,无需手动修改navigationIcon
  • onResume中重新同步ActionBar与NavController,解决后台恢复时实例更新导致的关联失效
  • onSupportNavigateUp中实时获取NavController,避免持有旧引用

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 06:35:31