Android Navigation Component#3: Adding Options Menu and Navigation Drawer

Shashank Mohabia
DevlUp Labs
Published in
5 min readApr 3, 2020

In the previous two blogs of this series, we saw how to use navigation component for navigating using actions and for passing data between destinations. Now let’s see how can we use it to ease the process of creating options menu and navigation drawer.

Creating Options Menu

The options menu is the one accessible by clicking the three vertical dots that appear in the app bar (generally on the right side). It is the primary collection of menu items for an activity which may include actions like Search, Settings, and About us.

Generally, a menu file is created and each of its items is linked to their respective destinations progmatically. The navigation component makes it easier by removing the redundant code for linking the items to destinations. For creating an options menu, follow these steps:

Step 1. Create the destination fragment

The destination fragment must be in the nav graph for this to work. So if its not there add it or create a new destination. Let’s continue with our previous example and add a new destination to it named AboutUsFragment.

Step 2. Add the options menu resource:

Create a new android resource file named options_menu with Menu as the Resource type.

Add item to it like this:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/aboutUsFragment"
android:title="@string/about_us" />
</menu>

Note that the for navigation component to find the destination on its own keep the id of this item same as the id of the fragment in the nav graph.

Step 3. Use Navigation to setup toolbar:

First of all, enable the options menu for the fragment. For that modify onCreateView like this:

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
...
setHasOptionsMenu(true)

return binding.root
}

Now we have to override two methods of the class. First one is onCreateOptionsMenu()which is responsible for the inflating the menu using our menu file.

override fun onCreateOptionsMenu(menu: Menu?, inflater:MenuInflater?) {
super.onCreateOptionsMenu(menu, inflater)
inflater?.inflate(R.menu.options_menu, menu)
}

And second deals with the actions to be performed when an item gets clicked. Here comes the magic of Navigation components which saves us from linking each item to its destination and does the entire work with just one line of code.

override fun onOptionsItemSelected(item: MenuItem?): Boolean {
return NavigationUI.onNavDestinationSelected(item!!,
view!!.findNavController())

|| super.onOptionsItemSelected(item)
}

Note here that if an item has an action other than navigation(e.g saving data) then it has to be stated separately using its id like this:

override fun onOptionsItemSelected(item: MenuItem?): Boolean {
if(item.id == R.id.xyz){
do this action
return true
}

return NavigationUI.onNavDestinationSelected(item!!,
view!!.findNavController())
|| super.onOptionsItemSelected(item)
}

That's all that we have to do, navigation will take care of the rest. It’s easy right.😁

Creating a Navigation Drawer

The navigation drawer is a panel that slides out from the edge of the screen. The drawer typically contains a header and a menu.

On phone-sized devices, the navigation drawer is hidden when not in use. Two types of user actions can make the navigation drawer appear:

  • The drawer appears when the user swipes from the starting edge of the screen toward the ending edge of the screen.
  • The drawer appears when the user is at the start destination of the app and taps the drawer icon in the app bar. (The drawer icon is sometimes called the nav drawer button or hamburger icon)

It also needs a menu file like options menu but also a specific view. Let’s create one by following the steps given below:

Step 1. Add the Material library to your project:

In app level build.gradle add the following dependence for the material library(look for the latest version of supportlib):

dependencies {
...
implementation "com.google.android.material:material:$supportlibVersion"
...
}

Step 2. Make sure the destination fragments have IDs:

As discussed in the previous section that fragment IDs are required when creating a menu file, so check it and if it is not there then add it. And if the destination fragment is not there then add it or create it.

Step 3. Create the drawer menu and the drawer layout:

As done in the previous section create a navdrawer_menu.xml menu file in the resource folder and add items to it having the same IDs as the destination fragments.

Step 4. Create drawerLayout and navigationView:

For creating a navigation drawer we have to wrap the views in our activity_main.xml into a drawerLayout. And after all the content views at the end of the drawerLayout, we have to add a navigationView which will link our menu and header layout file(we can design the drawer header separately)to the drawer. The complete activity_main.xml looks like this:

Step 5. Display the navigation drawer from the drawer button

The final step is to enable the user to access the navigation drawer from the drawer button at the top left of the app bar.

  1. In the MainActivity.kt Kotlin file, add the lateinit drawerLayout member variable to represent the drawer layout:
private lateinit var drawerLayout: DrawerLayout

Note: Kotlin is a “null safety” language. One of the ways it offers null safety is through the lateinit modifier, which lets you delay the initialization of the variable without any danger of returning a null reference.

In this case, drawerLayout is declared with lateinit to avoid the need to make it nullable. It will be initialized in onCreate().

2. Inside the onCreate() method, initialize drawerLayout, after the binding variable has been initialized.

val binding = DataBindingUtil.setContentView<ActivityMainBinding>(this,R.layout.activity_main)
drawerLayout = binding.drawerLayout

3. Add the drawerLayout as the third parameter to the setupActionBarWithNavController() method:

NavigationUI.setupActionBarWithNavController(this, navController, drawerLayout)

4. Edit the onSupportNavigateUp() method to return NavigationUI.navigateUp instead of returning navController.navigateUp. Pass the navigation controller and the drawer layout to navigateUp(). The method will look like as follows:

override fun onSupportNavigateUp(): Boolean {
val navController = this.findNavController(R.id.myNavHostFragment)
return NavigationUI.navigateUp(navController, drawerLayout)
}

5. Run your app. Swipe from the left edge to display the navigation drawer, and make sure each of the menu items in the drawer goes to the right place.

6. Go to the home screen and tap the nav drawer button to make sure the navigation drawer appears. Make sure that clicking the options in the navigation drawer takes you to the right place.

That’s how simple is this with the help of the navigation component.

Note one thing that the options menu is set for a fragment but the navigation drawer for the entire activity. So you can distribute different options to these menus accordingly.

Feel free to comment if there are doubts or if you feel anything needs to be corrected😀.

References:

Android Kotlin Fundamentals codelab

--

--