Android Java中如何结合BottomNavigationView使用Jetpack Navigation
别担心!谷歌文档确实偏向Kotlin,但Java版本的实现其实很清晰,我帮你一步步梳理,解决重复代码的问题,同时实现点击菜单直接导航到NavGraph定义的页面。
第一步:确认依赖配置
首先确保你的app模块build.gradle里添加了Navigation的依赖(Java项目同样适用):
dependencies { // Navigation 核心库 implementation "androidx.navigation:navigation-fragment:2.7.7" implementation "androidx.navigation:navigation-ui:2.7.7" // Material Design(BottomNavigationView属于这个库) implementation "com.google.android.material:material:1.11.0" }
第二步:布局文件设置
在你的Activity布局(比如activity_main.xml)里,需要同时包含NavHostFragment容器和BottomNavigationView,结构如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout 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:orientation="vertical"> <!-- 承载导航页面的容器,必须指定NavHostFragment的类名和导航图 --> <androidx.fragment.app.FragmentContainerView android:id="@+id/nav_host_fragment" 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_nav_view" android:layout_width="match_parent" android:layout_height="wrap_content" app:menu="@menu/bottom_nav_menu" /> <!-- 关联菜单文件 --> </LinearLayout>
第三步:配置底部导航菜单
在res/menu/bottom_nav_menu.xml里定义底部菜单项,划重点:每个菜单项的id必须和NavGraph里的目的地id完全一致,否则导航不会生效:
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@id/home_fragment" <!-- 和nav_graph里的首页Fragment id一致 --> android:icon="@drawable/ic_home" android:title="首页" /> <item android:id="@id/profile_fragment" <!-- 和nav_graph里的个人中心Fragment id一致 --> android:icon="@drawable/ic_profile" android:title="我的" /> <item android:id="@id/settings_fragment" <!-- 和nav_graph里的设置Fragment id一致 --> android:icon="@drawable/ic_settings" android:title="设置" /> </menu>
第四步:Java代码实现绑定(解决重复代码问题)
在你的Activity的onCreate方法里,只需要一次绑定操作即可,不需要重复调用setupWithNavController。正确的写法如下:
import androidx.appcompat.app.AppCompatActivity; import androidx.navigation.NavController; import androidx.navigation.fragment.NavHostFragment; import androidx.navigation.ui.NavigationUI; import com.google.android.material.bottomnavigation.BottomNavigationView; import android.os.Bundle; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 1. 获取NavHostFragment和对应的NavController NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager() .findFragmentById(R.id.nav_host_fragment); NavController navController = navHostFragment.getNavController(); // 2. 获取BottomNavigationView并绑定NavController BottomNavigationView bottomNavView = findViewById(R.id.bottom_nav_view); NavigationUI.setupWithNavController(bottomNavView, navController); } }
为什么你的代码会重复?
你之前写的重复代码navigationUI.setupWithNavController(...)其实只需要调用一次,多次调用会重复注册导航监听,可能导致导航行为异常。上面的代码只在onCreate里执行一次绑定,就可以实现点击菜单直接跳转到NavGraph对应的页面。
额外注意事项
- ID匹配原则:必须保证菜单id和NavGraph里的目的地id完全相同(包括大小写),这是导航生效的核心前提。
- 自定义导航行为:如果需要修改默认导航逻辑(比如某些页面隐藏返回按钮、自定义切换动画),可以使用
AppBarConfiguration来配置:
import androidx.navigation.ui.AppBarConfiguration; // 在绑定前添加这段代码 AppBarConfiguration appBarConfig = new AppBarConfiguration.Builder( R.id.home_fragment, R.id.profile_fragment, R.id.settings_fragment) .build(); // 如果你的Activity有Toolbar,可以关联它 NavigationUI.setupActionBarWithNavController(this, navController, appBarConfig);
- 避免Fragment重复创建:NavController会自动管理Fragment的生命周期,不需要手动处理切换逻辑,确保你的NavGraph里的目的地都是正确的Fragment类。
这样设置完成后,点击BottomNavigationView的菜单项就会自动跳转到NavGraph中定义的对应页面啦,完全符合你的需求~
内容的提问来源于stack exchange,提问作者f1f1f0
相关产品推荐
相关产品推荐

