Android导航图搭配BottomNavigationView二次跳转子Fragment加载失效求助
问题解决:嵌套导航返回后子Fragment无法加载
问题描述
我有一个配置了导航图的MainActivity,包含FragmentA与BottomNavTestFragment两个Fragment。点击FragmentA中的按钮可跳转至BottomNavTestFragment,该Fragment内部集成了BottomNavigationView,且关联了包含FragmentB和FragmentC的独立导航图。首次跳转流程正常,但从BottomNavTestFragment返回FragmentA后,再次跳转至BottomNavTestFragment时,FragmentB和FragmentC无法加载。
相关代码片段
main_navigation_graph.xml
<?xml version="1.0" encoding="utf-8"?> <navigation xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/nav_test" app:startDestination="@id/fragmentA"> <fragment android:id="@+id/fragmentA" android:name="com.test.presentation.test.FragmentA" android:label="FragmentA" tools:layout="@layout/fragment_a"> <action android:id="@+id/action_fragmentA_to_BNavTestFragment" app:destination="@id/BNavTestFragment" /> </fragment> <fragment android:id="@+id/BNavTestFragment" android:name="com.test.presentation.test.BottomNavTestFragment" android:label="BNavTestFragment" tools:layout="@layout/fragment_b_nav_test" /> </navigation>
bottom_nav_graph.xml
<?xml version="1.0" encoding="utf-8"?> <navigation xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/nav_test_bottom" app:startDestination="@id/orderFragment"> <fragment android:id="@+id/orderFragment" android:name="com.test.presentation.test.FragmentB" android:label="FragmentB" tools:layout="@layout/fragment_b" /> <fragment android:id="@+id/profileFragment" android:name="com.test.presentation.test.FragmentC" android:label="FragmentC" tools:layout="@layout/fragment_c" /> </navigation>
fragment_layout_of_bottom_navigation.xml
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#E0668F"> <!-- Fragment Container for Navigation --> <androidx.fragment.app.FragmentContainerView android:id="@+id/nav_host_member_bottom_nav" android:name="androidx.navigation.fragment.NavHostFragment" android:layout_width="0dp" android:layout_height="0dp" app:defaultNavHost="true" app:layout_constraintBottom_toTopOf="@+id/bottom_navigation" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:navGraph="@navigation/nav_test_bottom_view" /> <!-- BottomNavigationView --> <com.google.android.material.bottomnavigation.BottomNavigationView android:id="@+id/bottom_navigation" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_gravity="bottom" app:backgroundTint="@color/primary_variant" app:itemIconTint="@color/bottom_nav_item_color" app:itemTextColor="@color/bottom_nav_item_text_color" app:labelVisibilityMode="labeled" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:menu="@menu/bottom_nav_menu_test" /> </androidx.constraintlayout.widget.ConstraintLayout>
menu.xml
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/orderFragment" android:icon="@drawable/ic_bottom_menu_orders" android:title="@string/bt_menu_orders" /> <item android:id="@+id/profileFragment" android:icon="@drawable/ic_bottom_menu_profile" android:title="@string/bt_menu_profile" /> </menu>
BottomNavFragment.kt 初始化代码
private fun setUpBottomNavigation() { val navHostFragment = requireActivity().supportFragmentManager .findFragmentById(R.id.nav_host_member_bottom_nav) as NavHostFragment val navController: NavController = navHostFragment.navController val bottomNavigationView = requireView().findViewById<BottomNavigationView>(R.id.bottom_navigation) bottomNavigationView.setupWithNavController(navController) }
问题原因
- FragmentManager使用错误:用
requireActivity().supportFragmentManager查找嵌套的NavHostFragment,返回后Activity的FragmentManager会保留旧的NavHost实例,再次进入时无法匹配新创建的BottomNavTestFragment的视图,导致找不到正确的NavHost。 - defaultNavHost属性冲突:嵌套的NavHost设置
app:defaultNavHost="true"会拦截返回键,干扰主导航栈的状态,导致Fragment重建时导航逻辑混乱。 - 导航绑定时机问题:如果初始化逻辑没有在每次视图创建时执行,Fragment重建时无法重新绑定导航关系。
解决方案
1. 改用ChildFragmentManager查找NavHostFragment
修改BottomNavTestFragment的setUpBottomNavigation方法,使用当前Fragment的childFragmentManager而非Activity的FragmentManager:
private fun setUpBottomNavigation() { val navHostFragment = childFragmentManager .findFragmentById(R.id.nav_host_member_bottom_nav) as NavHostFragment val navController: NavController = navHostFragment.navController val bottomNavigationView = requireView().findViewById<BottomNavigationView>(R.id.bottom_navigation) bottomNavigationView.setupWithNavController(navController) }
2. 移除嵌套NavHost的defaultNavHost属性
修改fragment_layout_of_bottom_navigation.xml中的FragmentContainerView,去掉app:defaultNavHost="true",让主导航栈处理返回逻辑:
<androidx.fragment.app.FragmentContainerView android:id="@+id/nav_host_member_bottom_nav" android:name="androidx.navigation.fragment.NavHostFragment" android:layout_width="0dp" android:layout_height="0dp" app:layout_constraintBottom_toTopOf="@+id/bottom_navigation" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:navGraph="@navigation/nav_test_bottom" />
注意:修正app:navGraph指向正确的bottom_nav_graph.xml,原代码中的@navigation/nav_test_bottom_view是错误的
3. 确保每次视图创建时初始化导航
在BottomNavTestFragment的onViewCreated方法中调用初始化逻辑,保证Fragment重建时重新绑定导航:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) setUpBottomNavigation() }
内容的提问来源于stack exchange,提问作者darwin
相关产品推荐
相关产品推荐

