Bottom navigation bars allow movement between primary destinations in an app.
Contents
Before you can use the Material bottom navigation, you need to add a dependency to the Material Components for Android library. For more information, go to the Getting started page.
A typical layout looks like this:
<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="wrap_content">
...
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:menu="@menu/bottom_navigation_menu" />
</LinearLayout>The @menu/bottom_navigation_menu resource should point to a file named
bottom_navigation_menu.xml inside a menu resource directory:
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/item_1"
android:enabled="true"
android:icon="@drawable/icon_1"
android:title="@string/text_label_1"/>
<item
android:id="@+id/item_2"
android:enabled="true"
android:icon="@drawable/icon_2"
android:title="@string/text_label_2"/>
</menu>Note: BottomNavigationView does not support more than 5 menu items.
In code:
NavigationBarView.OnItemSelectedListener { item ->
when(item.itemId) {
R.id.item_1 -> {
// Respond to navigation item 1 click
true
}
R.id.item_2 -> {
// Respond to navigation item 2 click
true
}
else -> false
}
}There's also a method for detecting when navigation items have been reselected:
bottomNavigation.setOnItemReselectedListener { item ->
when(item.itemId) {
R.id.item_1 -> {
// Respond to navigation item 1 reselection
}
R.id.item_2 -> {
// Respond to navigation item 2 reselection
}
}
}That results in:
Note: We have deprecated the
BottomNavigationView#setOnNavigationItemSelectedListener and
BottomNavigationView#setOnNavigationItemReselectedListener methods in favor of
the listeners in NavigationBarView. This allows you to share selection
handling code between the BottomNavigation and NavigationRail view elements.
You should set an android:title for each of your menu items so that screen
readers like TalkBack can properly announce what each navigation item
represents:
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
...
android:title="@string/text_label"/>
...
</menu>The labelVisibilityMode attribute can be used to adjust the behavior of the
text labels for each navigation item. There are four visibility modes:
LABEL_VISIBILITY_AUTO(default): The label behaves as “labeled” when there are 3 items or less, or “selected” when there are 4 items or moreLABEL_VISIBILITY_SELECTED: The label is only shown on the selected navigation itemLABEL_VISIBILITY_LABELED: The label is shown on all navigation itemsLABEL_VISIBILITY_UNLABELED: The label is hidden for all navigation items
Initialize and show a BadgeDrawable associated with menuItemId, subsequent
calls to this method will reuse the existing BadgeDrawable:
var badge = bottomNavigation.getOrCreateBadge(menuItemId)
badge.isVisible = true
// An icon only badge will be displayed unless a number is set:
badge.number = 99As a best practice, if you need to temporarily hide the badge, for instance
until the next notification is received, change the visibility of
BadgeDrawable:
val badgeDrawable = bottomNavigation.getBadge(menuItemId)
if (badgeDrawable != null) {
badgeDrawable.isVisible = false
badgeDrawable.clearNumber()
}To remove any BadgeDrawables that are no longer needed:
bottomNavigation.removeBadge(menuItemId)See the BadgeDrawable documentation for more information
about badges.
API and source code:
BottomNavigationView
The following example shows a bottom navigation bar with four icons:
In layout.xml:
<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="wrap_content">
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:menu="@menu/bottom_navigation_menu" />
</LinearLayout>In bottom_navigation_menu.xml inside a menu resource directory:
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/page_1"
android:enabled="true"
android:icon="@drawable/ic_star"
android:title="@string/page_1"/>
<item
android:id="@+id/page_2"
android:enabled="true"
android:icon="@drawable/ic_star"
android:title="@string/page_2"/>
<item
android:id="@+id/page_3"
android:enabled="true"
android:icon="@drawable/ic_star"
android:title="@string/page_3"/>
<item
android:id="@+id/page_4"
android:enabled="true"
android:icon="@drawable/ic_star"
android:title="@string/page_4"/>
</menu>In code:
bottomNavigation.selectedItemId = R.id.page_2The following is an anatomy diagram for the bottom navigation bar:
- (1) Container
- (2) Icon
- (3) Label text
- (4) Active indicator
- (5) Small badge (optional)
- (6) Large badge (optional)
- (7) Large badge number
| Element | Attribute | Related methods | Default value |
|---|---|---|---|
| Color | app:backgroundTint |
N/A | ?attr/colorSurface |
| Elevation | app:elevation |
setElevation |
3dp |
| Compat Shadow | compatShadowEnabled |
N/A | false |
| Element | Attribute | Related methods | Default value |
|---|---|---|---|
| Menu resource | app:menu |
inflateMenugetMenu |
N/A |
| Ripple (inactive) | app:itemRippleColor |
setItemRippleColorgetItemRippleColor |
Variations of ?attr/colorPrimary and ?attr/colorOnSurfaceVariant (see all states) |
| Ripple (active) | " | " | Variations of ?attr/colorPrimary (see all states) |
| Label visibility mode | app:labelVisibilityMode |
setLabelVisibilityModegetLabelVisibilityMode |
LABEL_VISIBILITY_AUTO |
| Element | Attribute | Related methods | Default value |
|---|---|---|---|
| Icon | android:icon in the menu resource |
N/A | N/A |
| Size | app:itemIconSize |
setItemIconSizesetItemIconSizeResgetItemIconSize |
24dp |
| Color (inactive) | app:itemIconTint |
setItemIconTintListgetItemIconTintList |
?attr/colorOnSurfaceVariant (see all states) |
| Color (active) | " | " | ?attr/colorOnSecondaryContainer (see all states) |
| Element | Attribute | Related methods | Default value |
|---|---|---|---|
| Text label | android:title in the menu resource |
N/A | N/A |
| Color (inactive) | app:itemTextColor |
setItemTextColorgetItemTextColor |
?attr/colorOnSurfaceVariant (see all states) |
| Color (active) | " | " | ?attr/colorOnSurface (see all states) |
| Typography (inactive) | app:itemTextAppearanceInactive |
setItemTextAppearanceInactivegetItemTextAppearanceInactive |
?attr/textAppearanceTitleSmall |
| Typography (active) | app:itemTextAppearanceActive |
setItemTextAppearanceActivegetItemTextAppearanceActive |
?attr/textAppearanceTitleSmall |
| Element | Style | Container color | Icon/Text label color (inactive) | Icon/Text label color (active) |
|---|---|---|---|---|
| Default style | Widget.Material3.BottomNavigationView |
?attr/colorSurface |
?attr/colorOnSurfaceVariant |
Icon: ?attr/colorOnSecondaryContainer Text: ?attr/colorOnSurface |
Default style theme attribute: ?attr/bottomNavigationStyle
See the full list of styles, navigation bar attributes, and bottom navigation attributes.
Bottom navigation supports Material Theming, which can customize color and typography.
API and source code:
BottomNavigationView
The following example shows a bottom navigation bar with Material Theming.
Use theme attributes and a style in res/values/styles.xml, which applies to
all bottom navigation bars and affects other components:
<style name="Theme.App" parent="Theme.Material3.*">
...
<item name="colorSurface">@color/shrine_theme_light_surface</item>
<item name="colorOnSurfaceVariant">@color/shrine_theme_light_onSurfaceVariant</item>
</style>Use a default style theme attribute, styles, and a theme overlay, which apply to all bottom navigation bars but do not affect other components:
<style name="Theme.App" parent="Theme.Material3.*">
...
<item name="bottomNavigationStyle">@style/Widget.App.BottomNavigationView</item>
</style>
<style name="Widget.App.BottomNavigationView" parent="Widget.Material3.BottomNavigationView">
<item name="materialThemeOverlay">@style/ThemeOverlay.App.BottomNavigationView</item>
</style>
<style name="ThemeOverlay.App.BottomNavigationView" parent="">
<item name="colorSurface">@color/shrine_theme_light_surface</item>
<item name="colorOnSurfaceVariant">@color/shrine_theme_light_onSurfaceVariant</item>
</style>Use the style in the layout, which affects only this specific bottom navigation bar:
<com.google.android.material.bottomnavigation.BottomNavigationView
...
style="@style/Widget.App.BottomNavigationView"
/>




