# Bottom navigation (Navigation bar) [Navigation bar](https://m3.material.io/components/navigation-bar/overview) lets people switch between UI views on smaller devices. **Note:** The design name of this component has been changed from **Bottom navigation** to **Navigation bar**. However, Material's Android implementation remains as `BottomNavigationView`. Navigation bar with 4 icons. Navigation bar on compact and medium window sizes Navigation bars can have three to five destinations. The nav bar is positioned at the bottom of screens for convenient access. Each destination is represented by an icon and label text. **Note:** Images use various dynamic color schemes. ## Design & API documentation * [Material 3 (M3) spec](https://m3.material.io/components/navigation-bar/overview) * [API reference](https://developer.android.com/reference/com/google/android/material/bottomnavigation/package-summary) ## Anatomy ![Navigation bar anatomy diagram](assets/bottomnav/bottomnav-anatomy.png) 1. Container 2. Icon 3. Label text 4. Active indicator 5. Small badge (optional) 6. Large badge (optional) 7. Large badge label More details on anatomy items in the [component guidelines](https://m3.material.io/components/navigation-bar/guidelines#895b5b49-a166-4d30-90be-c71a4c970f04). ## M3 Expressive ### M3 Expressive update Before you can use `Material3Expressive` component styles, follow the [`Material3Expressive` themes setup instructions](https://github.com/material-components/material-components-android/tree/master/docs/getting-started.md#material3expressive-themes). A new expressive style for the bottom navigation bar has been introduced that's shorter and supports horizontal navigation items in medium-sized windows. [More on M3 Expressive](https://m3.material.io/blog/building-with-m3-expressive) Flexible horizontal navigation bar **Color:** * Active label changed from **on-surface-variant** to **secondary** ### M3 Expressive styles Changes from M3: * Height: From 80dp to 64dp * Color: New expressive colors! * Top item padding: From 12dp to 6dp * Bottom item padding: From 16dp to 6dp * Label text is no longer bolded when selected * Active indicator: From 64dp to 56dp * New horizontal item configuration on medium and larger window sizes (greater than or equal to 600dp): * Icon moves from top to start of item * Instead of being a set width based on the item count, item width is based on content with a max width * Item gravity: From top center to center The default style for bottom navigation bar is: ```xml @style/Widget.Material3Expressive.BottomNavigationView ``` ## Key properties ### Container attributes Element | Attribute | Related methods | Default value ------------------------------ | --------------------- | --------------- | ------------- **Color** | `app:backgroundTint` | N/A | `?attr/colorSurfaceContainer` **Elevation** | `app:elevation` | `setElevation` | `3dp` **Compat Shadow** (deprecated) | `compatShadowEnabled` | N/A | `false` **Note:** `compatShadowEnabled` has no effect, as the library no longer supports pre-Lollipop. ### Navigation bar item attributes 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](https://github.com/material-components/material-components-android/tree/master/lib/java/com/google/android/material/bottomnavigation/res/color/m3_navigation_bar_ripple_color_selector.xml)) **Ripple (active)** | " | " | Variations of `?attr/colorPrimary` (see all [states](https://github.com/material-components/material-components-android/tree/master/lib/java/com/google/android/material/bottomnavigation/res/color/m3_navigation_bar_ripple_color_selector.xml)) **Label visibility mode** | `app:labelVisibilityMode` | `setLabelVisibilityMode`
`getLabelVisibilityMode` | `LABEL_VISIBILITY_AUTO` **Item Gravity** | `app:itemGravity` | `setItemGravity`
`getItemGravity` | `TOP_CENTER` ### Active indicator attributes Element | Attribute | Related methods | Default value --------------------------------------- | ------------------------------------------ | ----------------------------------------------------------------------------------------------------- | ------------- **Color** | `android:color` | `setItemActiveIndicatorColor`
`getItemActiveIndicatorColor` | `?attr/colorSecondaryContainer` **Width** | `android:width` | `setItemActiveIndicatorWidth`
`getItemActiveIndicatorWidth` | `56dp` **Height** | `android:height` | `setItemActiveIndicatorHeight`
`getItemActiveIndicatorHeight` | `32dp` **Shape** | `app:shapeAppearance` | `setItemActiveIndicatorShapeAppearance`
`getItemActiveIndicatorShapeAppearance` | `50% rounded` **Margin horizontal** | `app:marginHorizontal` | `setItemActiveIndicatorMarginHorizontal`
`getItemActiveIndicatorMarginHorizontal` | `4dp` **Padding between indicator and label** | `app:activeIndicatorLabelPadding` | `setActiveIndicatorLabelPadding`
`getActiveIndicatorLabelPadding` | `4dp` **Expanded Width** | `app:expandedWidth` | `setItemActiveIndicatorExpandedWidth`
`getItemActiveIndicatorExpandedWidth` | `HUG` **Expanded Height** | `app:expandedHeight` | `setItemActiveIndicatorExpandedHeight`
`getItemActiveIndicatorExpandedHeight` | `56dp` **Expanded Margin horizontal** | `app:expandedMarginHorizontal` | `setItemActiveIndicatorExpandedMarginHorizontal`
`getItemActiveIndicatorExpandedMarginHorizontal` | `20dp` **Expanded Start Padding** | `app:expandedActiveIndicatorPaddingStart` | `setItemExpandedActiveIndicatorPadding` | `16dp` **Expanded End Padding** | `app:expandedActiveIndicatorPaddingEnd` | `setItemExpandedActiveIndicatorPadding` | `16dp` **Expanded Top Padding** | `app:expandedActiveIndicatorPaddingTop` | `setItemExpandedActiveIndicatorPadding` | `0dp` **Expanded Bottom Padding** | `app:expandedActiveIndicatorPaddingBottom` | `setItemExpandedActiveIndicatorPadding` | `0dp` **Note:** The expanded active indicator refers to the active indicator that expands to wrap the content of the navigation bar item when the `itemIconGravity` value is equal to `START`. ### Icon attributes 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](https://github.com/material-components/material-components-android/tree/master/lib/java/com/google/android/material/bottomnavigation/res/color/m3_navigation_bar_item_with_indicator_icon_tint.xml)) **Color (active)** | " | " | `?attr/colorOnSecondaryContainer` (see all [states](https://github.com/material-components/material-components-android/tree/master/lib/java/com/google/android/material/bottomnavigation/res/color/m3_navigation_bar_item_with_indicator_icon_tint.xml)) **Gravity** | `app:itemIconGravity` | `setItemIconGravity`
`getItemIconGravity` | `TOP` **Icon label horizontal padding** | `app:iconLabelHorizontalSpacing` | `setIconLabelHorizontalSpacing`
`getIconLabelHorizontalSpacing` | `4dp` ### Text label attributes 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](https://github.com/material-components/material-components-android/tree/master/lib/java/com/google/android/material/bottomnavigation/res/color/m3_navigation_bar_item_with_indicator_label_tint.xml)) **Color (active)** | " | " | `?attr/colorOnSurface` (see all [states](https://github.com/material-components/material-components-android/tree/master/lib/java/com/google/android/material/bottomnavigation/res/color/m3_navigation_bar_item_with_indicator_label_tint.xml)) **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:itemTextAppearanceActiveBoldEnabled` | `setItemTextAppearanceActiveBoldEnabled` | `true` **Max lines** | `app:labelMaxLines` | `setLabelMaxLines`
`getLabelMaxLines` | `1` **Scale with font size** | `app:scaleLabelWithFontSize` | `setScaleLabelTextWithFont`
`getScaleLabelTextWithFont` | `false` ### Styles Element | Style | Container color | Icon/Text label color (inactive) | Icon/Text label color (active) | Theme attribute ----------------- | --------------------------------------- | -------------------- | -------------------------------- | -------------------------------------------------------------------------- | --------------- **Default style** | `Widget.Material3.BottomNavigationView` | `?attr/colorSurface` | `?attr/colorOnSurfaceVariant` | Icon: `?attr/colorOnSecondaryContainer`
Text: `?attr/colorOnSurface` | `?attr/bottomNavigationStyle` For the full list, see [styles](https://github.com/material-components/material-components-android/tree/master/lib/java/com/google/android/material/bottomnavigation/res/values/styles.xml), [navigation attributes](https://github.com/material-components/material-components-android/tree/master/lib/java/com/google/android/material/navigation/res/values/attrs.xml), and [navigation bar attributes](https://github.com/material-components/material-components-android/tree/master/lib/java/com/google/android/material/bottomnavigation/res/values/attrs.xml). ## Code implementation Before you can use the Material navigation bar, you need to add a dependency to the Material components for Android library. For more information, go to the [Getting started](https://github.com/material-components/material-components-android/tree/master/docs/getting-started.md) page. ### Adding navigation bar A typical layout looks like this: ```xml ... ``` The `@menu/bottom_navigation_menu` resource should point to a file named `bottom_navigation_menu.xml` inside a `menu` resource directory: ```xml ``` **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: 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. ### Navigation bar example The following example shows a navigation bar with four icons: Navigation bar with four icons. In `layout.xml`: ```xml ``` In `bottom_navigation_menu.xml` inside a `menu` resource directory: ```xml ``` In code: ```kt bottomNavigation.selectedItemId = R.id.page_2 ``` ### Adding navigation bar on larger screens On medium screen sizes and larger, navigation bars are recommended to be a horizontal item configuration, by setting `app:itemIconGravity` to be `start` instead of `top`. You can do this by [setting alternative layouts identified by resource qualifiers](https://developer.android.com/develop/ui/views/layout/responsive-adaptive-design-with-views#alternative_layout_resources). Here's an example: ```xml ``` Horizontal navigation bar larger screens ### Making navigation bar 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 ... ``` The `labelVisibilityMode` attribute can be used to adjust the behavior of the text labels for each navigation bar 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 Navigation bar 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 `BadgeDrawable`s that are no longer needed: ```kt bottomNavigation.removeBadge(menuItemId) ``` See the [`Badges`](BadgeDrawable.md) documentation for more information about badges. ## Customizing navigation bar ### Theming a navigation bar Navigation bars support the customization of color and typography. #### Navigation bar theming example API and source code: * `BottomNavigationView` * [Class description](https://developer.android.com/reference/com/google/android/material/bottomnavigation/BottomNavigationView) * [Class source](https://github.com/material-components/material-components-android/tree/master/lib/java/com/google/android/material/bottomnavigation/BottomNavigationView.java) The following example shows a navigation bar with Material theming. Navigation bar with brown icons (favorites, music, places, news) and pink background. ##### Implementing navigation bar theming Use theme attributes and a style in `res/values/styles.xml`, which applies to all navigation bars and affects other components: ```xml ``` Use a default style theme attribute, styles, and a theme overlay, which apply to all navigation bars but do not affect other components: ```xml ``` Use the style in the layout, which affects only this specific navigation bar: ```xml ```