BottomNavigationView结合Navigation组件返回键按下时菜单项不高亮
使用BottomNavigationView搭配Navigation组件时,点击返回键后Fragment栈能正常处理,但BottomNavigationView的菜单项选中状态不会切换,始终停留在最后点击的项上。已确认nav_graph中的Fragment ID与BottomNavigationView菜单项ID完全匹配,相关代码如下:
nav_graph.xml
<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_graph" app:startDestination="@id/journalFragment"> <fragment android:id="@+id/journalFragment" android:name="com.example.Fragment1" android:label="@string/navigation_title_journal" tools:layout="@layout/fragment_journal"/> <fragment android:id="@+id/toolsFragment" android:name="com.example.Fragment2" android:label="@string/navigation_title_tools" tools:layout="@layout/fragment_tools" /> </navigation>
bottom_navigation_menu.xml
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/journalFragment" android:enabled="true" android:title="@string/navigation_title_journal" /> <item android:id="@+id/toolsFragment" android:enabled="true" android:title="@string/navigation_title_tools" /> </menu>
MainActivity onCreate方法代码
NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.nav_host_container); navController = navHostFragment.getNavController(); appBarConfiguration = new AppBarConfiguration.Builder( R.id.journalFragment, R.id.toolsFragment).build(); setupWithNavController(mToolbar, navController, appBarConfiguration); bottomNavigationView.setOnItemSelectedListener(item -> { Log.d("MainActivity", "setOnItemSelectedListener-------"); switch (item.getItemId()) { case R.id.dreamJournalFragment -> navController.navigate(R.id.dreamJournalFragment); case R.id.statisticsFragment -> navController.navigate(R.id.statisticsFragment); case R.id.toolsFragment -> navController.navigate(R.id.toolsFragment); case R.id.wikiFragment -> navController.navigate(R.id.wikiFragment); } return true; }); bottomNavigationView.setOnItemReselectedListener(item -> { // Ignore });
activity_main布局代码
<androidx.fragment.app.FragmentContainerView android:id="@+id/nav_host_container" android:name="androidx.navigation.fragment.NavHostFragment" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" app:defaultNavHost="true" app:navGraph="@navigation/nav_graph" /> <com.google.android.material.bottomnavigation.BottomNavigationView android:id="@+id/bottom_navigation" android:layout_width="match_parent" android:layout_height="wrap_content" app:menu="@menu/bottom_navigation_menu" />
问题原因
你手动实现了OnItemSelectedListener处理底部导航跳转,但没有监听NavController的目的地变化。点击返回键时,NavController的目的地会回退,但BottomNavigationView未收到变化通知,导致选中状态无法同步更新。
解决方法
方法1:使用官方绑定方法(推荐)
Navigation组件提供的BottomNavigationView.setupWithNavController()方法,可自动处理导航跳转、选中状态同步(包括返回键场景),无需手动编写监听逻辑。
修改MainActivity代码,删除自定义的setOnItemSelectedListener和setOnItemReselectedListener,替换为:
bottomNavigationView.setupWithNavController(navController);
该方法会自动完成:
- 点击底部菜单项时跳转到对应目的地
NavController目的地变化(含返回操作)时,自动更新BottomNavigationView选中项- 默认处理重复点击(避免重复入栈)
方法2:自定义逻辑时添加目的地监听
若需保留自定义OnItemSelectedListener,需添加NavController.OnDestinationChangedListener监听目的地变化,手动同步选中状态:
navController.addOnDestinationChangedListener((controller, destination, arguments) -> { if (destination.getId() == R.id.journalFragment || destination.getId() == R.id.toolsFragment) { bottomNavigationView.setSelectedItemId(destination.getId()); } });
此代码会在NavController目的地变化时,自动更新BottomNavigationView的选中项。
内容的提问来源于stack exchange,提问作者Chris B.
相关产品推荐
相关产品推荐

