Implementing BottomAppBar II: Menu and Navigation Drawer Control

Fırat Karababa
Material Design in Action
4 min readJun 17, 2018

In the previous article, we have discussed the basics of BottomAppBar which is introduced recently in I/O 2018 as a part of Material Components for Android. We have looked at how to implement BottomAppBar and explored its attributes. BottomAppBar inherits the ability to display menu items and navigation drawer control which we have been using as a part of Toolbar.

Toolbar menu icons and Navigation control (Illustration)

With the new BottomAppBar component, navigation control and toolbar menu items should be placed as a part of BottomAppBar. Following sections will show how to use Menu and Navigation Control with BottomAppBar.

BottomAppBar menu and Navigation control

BottomAppBar Menu

First an xml menu file should be created under res/menu directory for the menu items that are desired to be shown on BottomAppBar. Here is my bottomappbar_menu.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">

<item
android:id="@+id/app_bar_fav"
android:icon="@drawable/baseline_favorite_white_24"
android:title="@string/action_favorite"
app:showAsAction="ifRoom"/>

<item
android:id="@+id/app_bar_search"
android:icon="@drawable/baseline_search_white_24"
android:title="@string/action_search"
app:showAsAction="ifRoom"/>
<item
android:id="@+id/app_bar_settings"
android:title="@string/action_settings"
app:showAsAction="never"/>
</menu>

In the MainActivity where you have setSupportActionBar(bottom_app_bar) do the following.

override fun onCreateOptionsMenu(menu: Menu): Boolean {
val inflater = menuInflater
inflater.inflate(R.menu.bottomappbar_menu, menu)
return true
}

Now the menu items should be shown within BottomAppBar.

Handling Menu Item Click

In order to handle the BottomAppBar menu item clicks include the following code in your MainActivity.

override fun onOptionsItemSelected(item: MenuItem?): Boolean {
when (item!!.itemId) {
R.id.app_bar_fav -> toast("Fav menu item is clicked!")
R.id.app_bar_search -> toast("Search menu item is clicked!")
R.id.app_bar_settings -> toast("Settings item is clicked!")
}

return true
}

BottomAppBar menu is all set and should function correctly now.

BottomAppBar action menu item clicks

Navigation Drawer Control With BottomAppBar

Traditionally Navigation Drawer control is done with a NavigationView placed at the left side of the app. With BottomAppBar, navigation drawer behaviours have also been changing. The new Bottom Navigation Drawer which is used with BottomAppBar will be a Modal Bottom Sheet.

For navigation drawer control, first a Bottom Sheet is to be created. Below code is the layout file of the bottom sheet.

fragment_bottomsheet.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">


<com.google.android.material.navigation.NavigationView
android:id="@+id/navigation_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:menu="@menu/bottom_nav_drawer_menu"/>

</androidx.constraintlayout.widget.ConstraintLayout>

A menu file for navigation drawer should be included under res/menu.

bottom_nav_drawer_menu.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<group android:checkableBehavior="none">
<item
android:id="@+id/nav1"
android:icon="@drawable/baseline_exposure_plus_1_black_24"
android:title="@string/nav_item1" />
<item
android:id="@+id/nav2"
android:icon="@drawable/baseline_replay_10_black_24"
android:title="@string/nav_item2" />
<item
android:id="@+id/nav3"
android:icon="@drawable/baseline_forward_10_black_24"
android:title="@string/nav_item3" />
</group>
</menu>

Then a class extending BottomSheetDialogFragment should be created which inflates bottom sheet layout above.


import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.google.android.material.bottomsheet.BottomSheetDialogFragment

class BottomNavigationDrawerFragment: BottomSheetDialogFragment() {

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_bottomsheet, container, false)
}
}

The following lines of code should be placed in the onOptionsItemSelected method that is used for menu item click handling. When navigation icon is clicked, an instance of BottomNavigationDrawerFragment is created and the Bottom Navigation View is shown.

android.R.id.home -> {
val bottomNavDrawerFragment = BottomNavigationDrawerFragment()
bottomNavDrawerFragment.show(supportFragmentManager, bottomNavDrawerFragment.tag)
}

Here is the main activity layout code.

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"
android:layout_height="match_parent">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">

<com.google.android.material.bottomappbar.BottomAppBar
android:id="@+id/bottom_app_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
app:backgroundTint="@color/colorPrimary"
app:fabAlignmentMode="center"
app:fabAttached="true"
app:navigationIcon="@drawable/baseline_menu_white_24"/>


<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/baseline_add_white_24"
app:layout_anchor="@id/bottom_app_bar" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

And for the navigation drawer item clicks you can use the following code inside the BottomNavigationDrawerFragment class.

navigation_view.setNavigationItemSelectedListener { menuItem ->
// Bottom Navigation Drawer menu item clicks
when (menuItem!!.itemId) {
R.id.nav1 -> context!!.toast(getString(R.string.nav1_clicked))
R.id.nav2 -> context!!.toast(getString(R.string.nav2_clicked))
R.id.nav3 -> context!!.toast(getString(R.string.nav3_clicked))
}
true
}
Bottom Navigation Drawer control

Feel free to ask questions and make comments. Also you can follow me on Twitter.

--

--