Skip to content

Bottom Navigation ​

Bottom navigation bars allow movement between primary destinations in an app.

"Bottom navigation bar with 4 icons"

Contents

Design and API Documentation ​

Using bottom navigation ​

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:

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>

The @menu/bottom_navigation_menu resource should point to a file named bottom_navigation_menu.xml inside a menu resource directory:

xml
<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:

kt
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:

kt
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:

Bottom navigation bar with a white background, one selected purple icon and
another unselected icon.

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.

Making bottom navigation accessible ​

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:

xml
<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 more
  • LABEL_VISIBILITY_SELECTED: The label is only shown on the selected navigation item
  • LABEL_VISIBILITY_LABELED: The label is shown on all navigation items
  • LABEL_VISIBILITY_UNLABELED: The label is hidden for all navigation items

Adding badges ​

Bottom navigation with 3 icons with badges, an icon only badge and two
numbered badges showing 99 and
999+

Initialize and show a BadgeDrawable associated with menuItemId, subsequent calls to this method will reuse the existing BadgeDrawable:

kt
var badge = bottomNavigation.getOrCreateBadge(menuItemId)
badge.isVisible = true
// An icon only badge will be displayed unless a number or text is set:
badge.number = 99  // or badge.text = "New"

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:

kt
val badgeDrawable = bottomNavigation.getBadge(menuItemId)
    if (badgeDrawable != null) {
        badgeDrawable.isVisible = false
        badgeDrawable.clearNumber()  // or badgeDrawable.clearText()
    }

To remove any BadgeDrawables that are no longer needed:

kt
bottomNavigation.removeBadge(menuItemId)

See the BadgeDrawable documentation for more information about badges.

Bottom navigation bar ​

Example bottom navigation bar with four icons along the bottom: favorites,
music, places, and news. The music icon is
selected

Bottom navigation bar example ​

API and source code:

The following example shows a bottom navigation bar with four icons:

Bottom navigation bar with four icons

In layout.xml:

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:

xml
<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:

kt
bottomNavigation.selectedItemId = R.id.page_2

Anatomy and key properties ​

The following is an anatomy diagram for the bottom navigation bar:

Bottom navigation anatomy diagram

  • (1) Container
  • (2) Icon
  • (3) Label text
  • (4) Active indicator
  • (5) Small badge (optional)
  • (6) Large badge (optional)
  • (7) Large badge number

Container attributes ​

ElementAttributeRelated methodsDefault value
Colorapp:backgroundTintN/A?attr/colorSurfaceContainer
Elevationapp:elevationsetElevation3dp
Compat Shadow (deprecated)compatShadowEnabledN/Afalse

Note: compatShadowEnabled has no effect, as the library no longer supports pre-Lollipop.

ElementAttributeRelated methodsDefault value
Menu resourceapp:menuinflateMenu
getMenu
N/A
Ripple (inactive)app:itemRippleColorsetItemRippleColor
getItemRippleColor
Variations of ?attr/colorPrimary and ?attr/colorOnSurfaceVariant (see all states)
Ripple (active)""Variations of ?attr/colorPrimary (see all states)
Label visibility modeapp:labelVisibilityModesetLabelVisibilityMode
getLabelVisibilityMode
LABEL_VISIBILITY_AUTO
Item Gravityapp:itemGravitysetItemGravity
getItemGravity
TOP_CENTER

Active indicator attributes ​

ElementAttributeRelated methodsDefault value
Colorandroid:colorsetItemActiveIndicatorColor
getItemActiveIndicatorColor
?attr/colorSecondaryContainer
Widthandroid:widthsetItemActiveIndicatorWidth
getItemActiveIndicatorWidth
56dp
Heightandroid:heightsetItemActiveIndicatorHeight
getItemActiveIndicatorHeight
32dp
Shapeapp:shapeAppearancesetItemActiveIndicatorShapeAppearance
getItemActiveIndicatorShapeAppearance
50% rounded
Margin horizontalapp:marginHorizontalsetItemActiveIndicatorMarginHorizontal
getItemActiveIndicatorMarginHorizontal
4dp
Padding between indicator and labelapp:activeIndicatorLabelPaddingsetActiveIndicatorLabelPadding
getActiveIndicatorLabelPadding
4dp
Expanded WidthexpandedWidthsetItemExpandedActiveIndicatorWidth
getItemExpandedActiveIndicatorWidth
HUG
Expanded HeightexpandedHeightsetItemExpandedActiveIndicatorHeight
getItemExpandedActiveIndicatorHeight
56dp
Expanded Margin horizontalapp:expandedMarginHorizontalsetItemExpandedActiveIndicatorMarginHorizontal
getItemExpandedActiveIndicatorMarginHorizontal
20dp

Note: The expanded active indicator refers to the active indicator that expands to wrap the content of the Bottom Navigation item when the itemIconGravity value is equal to START.

Icon attributes ​

ElementAttributeRelated methodsDefault value
Iconandroid:icon in the menu resourceN/AN/A
Sizeapp:itemIconSizesetItemIconSize
setItemIconSizeRes
getItemIconSize
24dp
Color (inactive)app:itemIconTintsetItemIconTintList
getItemIconTintList
?attr/colorOnSurfaceVariant (see all states)
Color (active)""?attr/colorOnSecondaryContainer (see all states)
Gravityapp:itemIconGravitysetItemIconGravity
getItemIconGravity
TOP

Text label attributes ​

ElementAttributeRelated methodsDefault value
Text labelandroid:title in the menu resourceN/AN/A
Color (inactive)app:itemTextColorsetItemTextColor
getItemTextColor
?attr/colorOnSurfaceVariant (see all states)
Color (active)""?attr/colorOnSurface (see all states)
Typography (inactive)app:itemTextAppearanceInactive
app:horizontalItemTextAppearanceInactive
setItemTextAppearanceInactive
getItemTextAppearanceInactive
setHorizontalItemTextAppearanceInactive
getHorizontalItemTextAppearanceInactive
?attr/textAppearanceTitleSmall
Typography (active)app:itemTextAppearanceActive
app:horizontalItemTextAppearanceActive
setItemTextAppearanceActive
getItemTextAppearanceActive
setHorizontalItemTextAppearanceActive
getHorizontalItemTextAppearanceActive
?attr/textAppearanceTitleSmall
Typography (active)app:itemTextAppearanceActiveBoldEnabledsetItemTextAppearanceActiveBoldEnabledtrue

Styles ​

ElementStyleContainer colorIcon/Text label color (inactive)Icon/Text label color (active)
Default styleWidget.Material3.BottomNavigationView?attr/colorSurface?attr/colorOnSurfaceVariantIcon: ?attr/colorOnSecondaryContainer
Text: ?attr/colorOnSurface

Default style theme attribute: ?attr/bottomNavigationStyle

See the full list of styles, navigation bar attributes, and bottom navigation attributes.

Theming a bottom navigation bar ​

Bottom navigation supports Material Theming, which can customize color and typography.

Bottom navigation theming example ​

API and source code:

The following example shows a bottom navigation bar with Material Theming.

Bottom navigation bar with brown icons (favorites, music, places, news) and
pink background

Implementing bottom navigation theming ​

Use theme attributes and a style in res/values/styles.xml, which applies to all bottom navigation bars and affects other components:

xml
<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:

xml
<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:

xml
<com.google.android.material.bottomnavigation.BottomNavigationView
    ...
    style="@style/Widget.App.BottomNavigationView"
/>
Bottom Navigation has loaded