Android Bottom Navigation导航异常求助:无法正确切换Fragment
问题描述
我的应用包含4个Fragment,底部导航栏有3个图标。进入底部导航栏未包含的Fragment后,导航结构出现异常:
- 点击首页的食品图片进入FoodDetailFragment;
- 从该页面切换到BasketFragment后,无法切换回FoodListFragment;
- 点击底部导航栏的首页图标,会回到之前打开的FoodDetailFragment,而非首页。
我已在Activity中处理了所有Item点击事件,但问题仍未解决。相关代码如下:
Main Activity
@AndroidEntryPoint class FoodOrderingActivity : AppCompatActivity() { private lateinit var binding: ActivityFoodOrderingBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityFoodOrderingBinding.inflate(layoutInflater) setContentView(binding.root) val navHostFragment = supportFragmentManager .findFragmentById(R.id.food_ordering_fragment_container) as NavHostFragment NavigationUI.setupWithNavController(binding.bottomNavigationView, navHostFragment.navController) binding.bottomNavigationView.setOnItemReselectedListener{ when(it.itemId) { R.id.foodListFragment -> navHostFragment.findNavController().navigate(R.id.foodListFragment) //R.id.foodDetailFragment -> navHostFragment.findNavController().navigate(R.id.foodDetailFragment) R.id.basketFragment -> navHostFragment.findNavController().navigate(R.id.basketFragment) R.id.favoriteFoodFragment -> navHostFragment.findNavController().navigate(R.id.favoriteFoodFragment) } } } }
Navigation Graph
<?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/food_ordering_activity_nav_graph" app:startDestination="@id/foodListFragment"> <fragment android:id="@+id/foodListFragment" android:name="com.omersungur.foodorderingapp.ui.fragment.food_list.FoodListFragment" android:label="fragment_food_list" tools:layout="@layout/fragment_food_list" > <action android:id="@+id/action_foodListFragment_to_foodDetailFragment" app:destination="@id/foodDetailFragment" /> <action android:id="@+id/action_foodListFragment_to_basketFragment" app:destination="@id/basketFragment" /> </fragment> <fragment android:id="@+id/foodDetailFragment" android:name="com.omersungur.foodorderingapp.ui.fragment.food_detail.FoodDetailFragment" android:label="fragment_food_detail" tools:layout="@layout/fragment_food_detail" > <action android:id="@+id/action_foodDetailFragment_to_basketFragment" app:destination="@id/basketFragment" app:popUpTo="@id/foodDetailFragment" app:popUpToInclusive="true" /> <argument android:name="food" app:argType="com.omersungur.foodorderingapp.model.food.Food" /> </fragment> <fragment android:id="@+id/basketFragment" android:name="com.omersungur.foodorderingapp.ui.fragment.basket.BasketFragment" android:label="fragment_basket" tools:layout="@layout/fragment_basket" > <action android:id="@+id/action_basketFragment_to_foodListFragment" app:destination="@id/foodListFragment" app:popUpTo="@id/foodListFragment" /> </fragment> <fragment android:id="@+id/favoriteFoodFragment" android:name="com.omersungur.foodorderingapp.ui.fragment.favorite.FavoriteFoodFragment" android:label="fragment_favorite_food" tools:layout="@layout/fragment_favorite_food" /> </navigation>
Bottom Nav Menu
<menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/foodListFragment" android:layout_width="wrap_content" android:layout_height="wrap_content" android:icon="@drawable/ic_home" android:title="Home" /> <item android:id="@+id/favoriteFoodFragment" android:layout_width="wrap_content" android:layout_height="wrap_content" android:icon="@drawable/ic_favorite" android:title="Favorite" /> <item android:id="@+id/basketFragment" android:layout_width="wrap_content" android:layout_height="wrap_content" android:icon="@drawable/ic_basket" android:title="Basket" /> </menu>
解决方案
问题确实和**回退栈(BackStack)**直接相关,以下是具体修复步骤:
1. 修正Navigation Graph的Action配置
修改FoodDetailFragment到BasketFragment的Action
原来的Action只弹出自身,需要改成弹出到FoodListFragment(底部导航的根节点),确保从BasketFragment点击首页能直接回到FoodListFragment:
<action android:id="@+id/action_foodDetailFragment_to_basketFragment" app:destination="@id/basketFragment" app:popUpTo="@id/foodListFragment" app:popUpToInclusive="false" />
修正BasketFragment回到FoodListFragment的Action
确保返回时清空中间栈,避免残留页面:
<action android:id="@+id/action_basketFragment_to_foodListFragment" app:destination="@id/foodListFragment" app:popUpTo="@id/foodListFragment" app:popUpToInclusive="true" />
2. 移除Activity中多余的重选监听
NavigationUI.setupWithNavController已经默认处理了底部导航的点击和重选逻辑,额外添加的setOnItemReselectedListener会导致重复导航,干扰默认行为,直接删除这段代码:
// 删掉以下这段代码 binding.bottomNavigationView.setOnItemReselectedListener{ when(it.itemId) { R.id.foodListFragment -> navHostFragment.findNavController().navigate(R.id.foodListFragment) //R.id.foodDetailFragment -> navHostFragment.findNavController().navigate(R.id.foodDetailFragment) R.id.basketFragment -> navHostFragment.findNavController().navigate(R.id.basketFragment) R.id.favoriteFoodFragment -> navHostFragment.findNavController().navigate(R.id.favoriteFoodFragment) } }
3. 优化底部导航跳转的回退栈(可选)
在Navigation Graph中,给底部导航三个Fragment之间的跳转添加回退栈清理逻辑,比如修改FoodListFragment到BasketFragment的Action:
<action android:id="@+id/action_foodListFragment_to_basketFragment" app:destination="@id/basketFragment" app:popUpTo="@id/foodListFragment" app:popUpToInclusive="false" />
这样每次切换底部导航时,都会回到对应目的地的根实例,不会保留之前的子页面栈。
验证效果
- 从FoodListFragment进入FoodDetailFragment,再跳转到BasketFragment,回退栈里只会保留FoodListFragment和BasketFragment;
- 点击底部导航的首页图标,会直接回到FoodListFragment的根页面;
- 从BasketFragment切换到其他底部导航项再切回,也会回到BasketFragment的根实例。
内容的提问来源于stack exchange,提问作者omersungur
相关产品推荐
相关产品推荐

