Android:如何在含BottomNavigationBar的Activity中添加单Toolbar的NavigationDrawer
Hey there! Let's tackle this problem step by step. You want to swap out those per-fragment Toolbars for a single, unified ActionBar in your MainActivity that plays nice with both BottomNavigationBar and NavigationDrawer. Here's a clear, actionable solution:
First, restructure your MainActivity layout to use a DrawerLayout as the root container. This will wrap your new shared Toolbar, BottomNavigationView, Fragment container, and the NavigationView for the drawer. Here's the layout code:
<?xml version="1.0" encoding="utf-8"?> <androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/drawer_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true"> <!-- Main content area --> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <!-- Shared Toolbar (this becomes your ActionBar) --> <androidx.appcompat.widget.Toolbar android:id="@+id/main_toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:titleTextColor="@android:color/white"/> <!-- Fragment container --> <FrameLayout android:id="@+id/fragment_container" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1"/> <!-- BottomNavigationBar --> <com.google.android.material.bottomnavigation.BottomNavigationView android:id="@+id/bottom_nav" android:layout_width="match_parent" android:layout_height="wrap_content" app:menu="@menu/bottom_nav_menu"/> </LinearLayout> <!-- Navigation Drawer --> <com.google.android.material.navigation.NavigationView android:id="@+id/nav_view" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="start" app:menu="@menu/drawer_menu"/> </androidx.drawerlayout.widget.DrawerLayout>
Keep using the NoActionBar theme (since we're using a custom Toolbar as the ActionBar). Make sure your theme in styles.xml looks something like this:
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar"> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> </style>
Now, let's connect all the pieces in your MainActivity. We'll set the Toolbar as the support ActionBar, link it to the NavigationDrawer, handle BottomNavigation switches, and update the ActionBar title dynamically.
class MainActivity : AppCompatActivity() { private lateinit var drawerLayout: DrawerLayout private lateinit var appBarConfiguration: AppBarConfiguration override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // Set up the shared Toolbar as the ActionBar val toolbar = findViewById<Toolbar>(R.id.main_toolbar) setSupportActionBar(toolbar) // Initialize DrawerLayout and NavigationView drawerLayout = findViewById(R.id.drawer_layout) val navView = findViewById<NavigationView>(R.id.nav_view) // Configure which destinations show the drawer icon appBarConfiguration = AppBarConfiguration( setOf( R.id.home_fragment, R.id.search_fragment, R.id.add_fragment, R.id.notifications_fragment, R.id.profile_fragment ), drawerLayout ) // Link the ActionBar to the DrawerLayout with a toggle button val toggle = ActionBarDrawerToggle( this, drawerLayout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close ) drawerLayout.addDrawerListener(toggle) toggle.syncState() // Handle NavigationView menu clicks (customize this as needed) navView.setNavigationItemSelectedListener { menuItem -> // Add your drawer menu logic here drawerLayout.closeDrawer(GravityCompat.START) true } // Handle BottomNavigation switches val bottomNav = findViewById<BottomNavigationView>(R.id.bottom_nav) bottomNav.setOnItemSelectedListener { item -> val fragment = when (item.itemId) { R.id.home_fragment -> HomeFragment() R.id.search_fragment -> SearchFragment() R.id.add_fragment -> AddFragment() R.id.notifications_fragment -> NotificationsFragment() R.id.profile_fragment -> ProfileFragment() else -> return@setOnItemSelectedListener false } // Replace the current fragment supportFragmentManager.beginTransaction() .replace(R.id.fragment_container, fragment) .commit() // Update ActionBar title (or let fragments handle this, see step 5) supportActionBar?.title = when (item.itemId) { R.id.home_fragment -> "Home" R.id.search_fragment -> "Search" R.id.add_fragment -> "Add" R.id.notifications_fragment -> "Notifications" R.id.profile_fragment -> "Profile" else -> "" } true } // Load the default fragment on first launch if (savedInstanceState == null) { bottomNav.selectedItemId = R.id.home_fragment } } // Close drawer when back button is pressed (if open) override fun onBackPressed() { if (drawerLayout.isDrawerOpen(GravityCompat.START)) { drawerLayout.closeDrawer(GravityCompat.START) } else { super.onBackPressed() } } }
Go into each of your 5 Fragment layouts and delete the Toolbar elements—we don't need them anymore, since we're using the shared ActionBar from MainActivity.
If you prefer to keep title logic inside each Fragment (instead of hardcoding in MainActivity), you can set the title directly in each Fragment's onViewCreated method:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) requireActivity().supportActionBar?.title = "Home" // Replace with your fragment's title }
This keeps your code more decoupled—MainActivity only handles navigation, and Fragments manage their own display details.
- Drawer icon not showing? Double-check that you've initialized
ActionBarDrawerToggleand calledtoggle.syncState(), and that yourAppBarConfigurationincludes all your BottomNavigation destination IDs. - Title not updating? Make sure you're setting
supportActionBar?.titleeither in MainActivity's BottomNavigation listener or in the Fragment'sonViewCreated. - Drawer not sliding? Ensure your root layout is
DrawerLayout, the NavigationView haslayout_gravity="start", and the main content area doesn't have a gravity set.
内容的提问来源于stack exchange,提问作者Mahmoud Ayman

