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/page_1"
android:enabled="true"
android:icon="@drawable/icon_1"
android:title="@string/text_label_1"/>
<item
android:id="@+id/page_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.item1 -> {
// Respond to navigation item 1 click
true
}
R.id.item2 -> {
// 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.item1 -> {
// Respond to navigation item 1 reselection
}
R.id.item2 -> {
// 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 = 99
As 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 BadgeDrawable
s 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_2
The 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 |
inflateMenu getMenu |
N/A |
Ripple (inactive) | app:itemRippleColor |
setItemRippleColor getItemRippleColor |
Variations of ?attr/colorPrimary and ?attr/colorOnSurfaceVariant (see all states) |
Ripple (active) | " | " | Variations of ?attr/colorPrimary (see all states) |
Label visibility mode | app:labelVisibilityMode |
setLabelVisibilityMode getLabelVisibilityMode |
LABEL_VISIBILITY_AUTO |
Element | Attribute | Related methods | Default value |
---|---|---|---|
Icon | android:icon in the menu resource |
N/A | N/A |
Size | app:itemIconSize |
setItemIconSize setItemIconSizeRes getItemIconSize |
24dp |
Color (inactive) | app:itemIconTint |
setItemIconTintList getItemIconTintList |
?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 |
setItemTextColor getItemTextColor |
?attr/colorOnSurfaceVariant (see all states) |
Color (active) | " | " | ?attr/colorOnSurface (see all states) |
Typography (inactive) | app:itemTextAppearanceInactive |
setItemTextAppearanceInactive getItemTextAppearanceInactive |
?attr/textAppearanceTitleSmall |
Typography (active) | app:itemTextAppearanceActive |
setItemTextAppearanceActive getItemTextAppearanceActive |
?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_blue_100</item>
<item name="colorOnSurfaceVariant">@color/shrine_blue_900</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_blue_100</item>
<item name="colorOnSurfaceVariant">@color/shrine_blue_900</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"
/>