屏幕旋转时如何加载对应UI?使用Navigation Controller加载Fragment的实现问题
解决方案
问题根源
- 你混用了
supportFragmentManager直接操作Navigation托管的容器,和NavController的栈管理逻辑冲突 - 切回竖屏时仅重新绑定了ActionBar,没有清理横屏模式下手动添加的Fragment,导致多层Fragment叠加显示
实现步骤
1. 配置方向限定布局
首先在res目录下创建两个布局文件夹:
res/layout-port:存放竖屏模式的主布局,仅保留单个NavHostFragment容器,id为nav_host_fragment_content_mainres/layout-land:存放横屏模式的主布局,添加两个独立的Fragment容器,id分别为left_container、right_container
同时确认你已在AndroidManifest.xml对应Activity节点添加配置,避免旋转时Activity重建:
<activity android:name=".YourActivity" android:configChanges="orientation|screenSize|screenLayout" />
2. 修正配置变更逻辑
替换你原来的onConfigurationChanged代码,核心逻辑是横屏时手动管理两个Fragment,竖屏时先清理手动添加的Fragment再恢复Navigation托管:
override fun onConfigurationChanged(newConfig: Configuration) { super.onConfigurationChanged(newConfig) val navController = findNavController(R.id.nav_host_fragment_content_main) if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) { // 先获取当前Navigation栈顶的Fragment(即竖屏正在显示的页面) val currentFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment_content_main) ?.childFragmentManager?.primaryNavigationFragment // 隐藏NavHost避免叠加 supportFragmentManager.findFragmentById(R.id.nav_host_fragment_content_main)?.view?.visibility = View.GONE // 横屏加载两个Fragment supportFragmentManager.beginTransaction() .replace(R.id.left_container, currentFragment ?: FirstFragment()) .replace(R.id.right_container, SecondFragment()) // 替换为你要展示的第二个Fragment .commit() } else { // 先移除横屏时添加的所有Fragment supportFragmentManager.findFragmentById(R.id.left_container)?.let { supportFragmentManager.beginTransaction().remove(it).commit() } supportFragmentManager.findFragmentById(R.id.right_container)?.let { supportFragmentManager.beginTransaction().remove(it).commit() } // 恢复NavHost显示和ActionBar绑定 supportFragmentManager.findFragmentById(R.id.nav_host_fragment_content_main)?.view?.visibility = View.VISIBLE appBarConfiguration = AppBarConfiguration(navController.graph) setupActionBarWithNavController(navController, appBarConfiguration) } }
注意事项
- 不要直接操作
NavHostFragment内部的容器,会破坏Navigation的栈管理逻辑 - 切换方向时必须清理非Navigation托管的Fragment实例,避免重叠
- 若需要保留Fragment状态,可以通过
ViewModel存储页面数据,切换时直接复用实例即可
内容的提问来源于stack exchange,提问作者Prashant Gosai
相关产品推荐
相关产品推荐

