Integrating NavigationDrawer with NavigationComponent
This tutorial shows you how to integrating Navigation Component with Toolbar as ActionBar and NavigationDrawer.
NavigationUI class
Navigation Component includes a NavigationUI class. This class contains static methods for applying modifications to the top app bar and/or bottom app bar according to the user's navigation through the app. For example, this class automatically updates as users navigate through your app:- Top app bar's content (title and options menu);
- Top app bar's navigation button (hamburger icon for top-levels and a left-arrow for others when utilizing NavigationDrawer);
- Bottom navigation bar's selected item.
AppBarConfiguration
val appBarConfiguration = AppBarConfiguration(navController.graph, drawerLayout)
In some cases, you might need to define multiple top-level destinations instead of using the default start destination. Using a BottomNavigationView is a common use case for this, where you may have sibling screens that are not hierarchically related to each other and may each have their own set of related destinations. For cases like these, you can instead pass a set of destination IDs to the constructor, as shown below:
val appBarConfiguration = AppBarConfiguration(setOf(R.id.main, R.id.profile))
Steps to integrate NavigationDrawer with NavigationComponent
1. Create NavigationDrawer. In a nutshell, create a menu resource for Navigation Menu, create a DrawerLayout with a main content (that can be any normal layout types as LinearLayout or ConstraintLayout) and a NavigationView, and link NavigationView with menu resource with the tag app:menu. More details about NavigationDrawer and its implementation here.
2. Create a Toolbar and set this as ActionBar. Inside the main content of the DrawerLayout, creates a toolbar, as below:
<LinearLayout <!-- Main UI Content -->
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:minHeight="?attr/actionBarSize"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:titleTextColor="@android:color/white"
android:background="?attr/colorPrimary"/>
</LinearLayout>
And in the Activity's onCreate(), set this Toolbar as the app's ActionBar:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setSupportActionBar(findViewById(R.id.toolbar))
}
More details about Toolbar, ActionBar and its implementations, see here.
3. Create Navigation Component. In a nutshell, create navigation graph, add NavHost to the Activity's layout (make sure that the NavHost is contained in the layout that represents the main content inside the DrawerLayout, otherwise the Navigation Menu may not be displayed over the main layout when the user clicks Navigation Button), resulting:
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".view.MainActivity">
<LinearLayout <!-- Main UI Content -->
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:minHeight="?attr/actionBarSize"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:titleTextColor="@android:color/white"
android:background="?attr/colorPrimary"/>
<androidx.fragment.app.FragmentContainerView
android:name="androidx.navigation.fragment.NavHostFragment"
android:id="@+id/nav_host_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph" />
</LinearLayout>
<com.google.android.material.navigation.NavigationView
android:id="@+id/navigation_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:clipToPadding="false"
android:fitsSystemWindows="true"
app:menu="@menu/main_menu"
/>
</androidx.drawerlayout.widget.DrawerLayout>
4. Link NavigationView, NavController and NavigationUI. We need to setup NavController to orchestrates the swapping of fragments in the NavHost, based on selected menu option in the NavigationView (the ViewGroup for Navigation Menu). When utilizing Navigation Component, NavigationUI will open and close NavigationView and update the visual of the selected menu. All this links (NavigationView, NavController and NavigationUI) is made on Activity's onCreate():
class MainActivity : AppCompatActivity() {
private lateinit var drawerLayout: DrawerLayout
private lateinit var navController: NavController
private lateinit var appBarConfiguration:AppBarConfiguration
override fun onCreate(savedInstanceState: Bundle?) {
...
drawerLayout = findViewById<DrawerLayout>(R.id.drawer)
val navHostFragment =
supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
navController = navHostFragment.navController
findViewById<NavigationView>(R.id.navigation_view)
.setupWithNavController(navController)
}
}
More details about Navigation Component and its implementation here.
5. Informs NavigationUI that you use NavigationDrawer, since, in this case, NavigationUI will have to control the NavigationDrawer hamburger icon. This is done by creating an AppBarConfiguration in the following way:
appBarConfiguration = AppBarConfiguration(navController.graph, drawerLayout)
6. As we are utilizing a Toolbar as ActionBar, we need to call setupActionBarWithNavController() from our main activity's onCreate() method in this way:
setupActionBarWithNavController(navController, appBarConfiguration)
override fun onSupportNavigateUp(): Boolean {
Finally, our Activity's class is as below:
return navController.navigateUp(appBarConfiguration)
|| super.onSupportNavigateUp()
}
class MainActivity : AppCompatActivity() {
private lateinit var drawerLayout: DrawerLayout
private lateinit var navController: NavController
private lateinit var appBarConfiguration:AppBarConfiguration
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setSupportActionBar(findViewById(R.id.toolbar))
drawerLayout = findViewById<DrawerLayout>(R.id.drawer)
val navHostFragment =
supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
navController = navHostFragment.navController
findViewById<NavigationView>(R.id.navigation_view)
.setupWithNavController(navController)
appBarConfiguration = AppBarConfiguration(navController.graph, drawerLayout)
setupActionBarWithNavController(navController, appBarConfiguration)
}
override fun onSupportNavigateUp(): Boolean {
return navController.navigateUp(appBarConfiguration)
|| super.onSupportNavigateUp()
}
/*
override fun onBackPressed() {
if (drawerLayout.isDrawerOpen(GravityCompat.START)) {
drawerLayout.closeDrawer(GravityCompat.START)
} else {
super.onBackPressed()
}
}*/
}