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

Android Navigation框架下,Fragment控制宿主Activity中View显示隐藏:首次进入目标Fragment时View未隐藏的问题解决

解决首次进入SongDetailsFragment时底部控制栏未隐藏的问题

我来帮你搞定这个首次进入SongDetailsFragment时bottom_controls还显示的问题!咱们先分析下当前实现的问题,再给你两个靠谱的解决方案。

问题根源

你当前的实现里,在Fragment的生命周期方法(比如onActivityCreated、onResume)里通过supportFragmentManager.currentNavigationFragment判断当前页面,但首次导航到SongDetailsFragment时,Fragment的生命周期方法执行时机可能早于导航完成的时机,此时currentNavigationFragment还没更新成当前的SongDetailsFragment,导致判断逻辑走了showMiniPlayer(),所以底部栏没隐藏。另外,currentFragment == this as SongDetailsFragment这个判断也有点多余,强转的写法完全没必要。

解决方案

方案一:用Navigation的导航监听器(推荐)

这是官方推荐的监听页面导航变化的方式,能准确捕获每一次导航完成的事件,不管首次还是后续进入都能可靠触发。

在MainActivity.kt的onCreate方法里添加导航监听器:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    
    // 获取NavController
    val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
    val navController = navHostFragment.navController

    // 添加导航目标变化监听器
    navController.addOnDestinationChangedListener { _, destination, _ ->
        // 替换成你nav_graph里SongDetailsFragment的实际id
        if (destination.id == R.id.songDetailsFragment) {
            viewModel.hideMiniPlayer()
        } else {
            viewModel.showMiniPlayer()
        }
    }
}

然后移除MainActivity和BaseSongDetailFragment里原来的显示/隐藏判断逻辑,这个监听器会自动处理所有导航场景:只要进入SongDetailsFragment就隐藏底部栏,离开就显示,逻辑清晰还解耦。

方案二:修复Fragment生命周期里的逻辑

如果不想用导航监听器,可以修改BaseSongDetailFragment的逻辑,改用更可靠的生命周期方法,并且直接基于当前Fragment类型判断:

open class BaseSongDetailFragment : Fragment() {
    private val songDetailViewModel by sharedViewModel<SongDetailViewModel>()
    protected val mainViewModel by inject<MainViewModel>()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        showHideBottomSheet()
    }

    override fun onStop() {
        // 当Fragment停止(比如离开页面)时,显示底部栏
        mainViewModel.showMiniPlayer()
        super.onStop()
    }

    private fun showHideBottomSheet() {
        val currentData = songDetailViewModel.currentData.value ?: return
        if (currentData.id == 0L) return
        // 当前就是SongDetailsFragment的父类,直接执行隐藏逻辑
        mainViewModel.hideMiniPlayer()
    }
}

这里用onViewCreated(视图创建完成后)触发隐藏,onStop(页面退出时)触发显示,避免了首次进入时的时机问题,而且不需要再判断currentFragment,逻辑更简洁。

额外提示

记得检查是否有重复的显示/隐藏逻辑(比如MainActivity里的原有判断),如果有要移除,避免逻辑冲突导致的异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.01 00:12:34