Site icon Howtodoandroid

Navigation rail – Material Component For Android

Navigation rail poster

The rail is a side navigation component that displays three to seven app destinations and, optionally, a Floating Action Button. Each destination is represented by an icon and a text label.

The rail can function on its own at larger screen sizes, such as desktops and tablets. When users transition between screen sizes and devices, the rail can also complement other navigation components, such as bottom navigation.

Before getting into details, Checkout my other post on material design,

Sliders – Material Component For Android

ShapeableImageView – Material components for android [Example]

Progress Indicators – Material Components For Android

Android Chips – Material Component For Android

Navigation rails should be used for:

Navigation rails shouldn’t be used for:

Before we can get started, you need to add the dependency for the Android Material Components library. The Navigation Rail is only currently available in the latest release of1.4.0.

implementation ''

Adding Navigation Rail in layout

Create a new layout file or just add the NavigationRailView to one of your existing layouts like in the following XML snippet.

< android:id="@+id/navigation_rail" android:layout_width="wrap_content" android:layout_height="match_parent" app:menu="@menu/navigation_rail_menu" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" style="@style/Widget.MaterialComponents.NavigationRailView.Colored" />
Code language: HTML, XML (xml)

When adding this view to your layout, there are some typical guidelines that should be followed. These most likely depend on what your view hierarchy consists of, but as a general guide:

Adding Menu

The parameter app:menu takes a menu reference and holds all the navigation views to be displayed in the NavigationRailas menu items.

< android:id="@+id/navigation_rail" android:layout_width="wrap_content" android:layout_height="match_parent" app:menu="@menu/navigation_rail_menu" />
Code language: HTML, XML (xml)

An example menu navigation_rail_menu.xml look like this:

<menu xmlns:android=""> <item android:id="@+id/inbox" android:enabled="true" android:icon="@drawable/ic_baseline_inbox_24" android:title="Inbox"/> <item android:id="@+id/sent" android:enabled="true" android:icon="@drawable/ic_baseline_send_24" android:title="Sent"/> <item android:id="@+id/draft" android:enabled="true" android:icon="@drawable/ic_baseline_drafts_24" android:title="Draft"/> <item android:id="@+id/trash" android:enabled="true" android:icon="@drawable/ic_baseline_restore_from_trash_24" android:title="Trash"/> </menu>
Code language: HTML, XML (xml)

Menu Gravity

Navigation rail destinations can be aligned as a group to the top, bottom, or center of a layout. On tablets, bottom alignment can make destinations easier for a user to reach with their thumbs.

 app:menuGravity="top | center | bottom" 
< android:id="@+id/navigation_rail" android:layout_width="wrap_content" android:layout_height="match_parent" app:menu="@menu/navigation_rail_menu" app:menuGravity="top" />
Code language: HTML, XML (xml)

Menu Label Visibility

The label is only being shown for the currently selected item within the Rail. This is the default behavior for the label visibility and we can control this using the labelVisibilityMode attribute.

app:labelVisibilityMode="auto | labeled | selected | unlabeled"
< android:id="@+id/navigation_rail" android:layout_width="wrap_content" android:layout_height="match_parent" app:menu="@menu/navigation_rail_menu" app:labelVisibilityMode="auto" app:menuGravity="top"/>
Code language: HTML, XML (xml)

auto – when there are more than 3 items the Rail will use the selected option, otherwise, the labeled option will be applied.

labeled – Persistent text labels are visible at all times, regardless of a destination’s state.

selected – Selected text labels appear only when a destination is activated.

unlabeled – If all icons in the navigation rail can be expected to have clear meaning to users, labels can be omitted as a group.

Adding Layout Header

The rail provides a convenient container for anchoring the Floating Action Button (FAB) to the top of a screen, placing the app’s key action above navigation destinations.

Other than showing a menu inside of our Navigation Rail, we can provide a layout reference for the headerLayout an attribute of the view.


< android:id="@+id/navigation_rail" android:layout_width="wrap_content" android:layout_height="match_parent" app:menu="@menu/navigation_rail_menu" app:headerLayout="@layout/layout_fab" app:labelVisibilityMode="labeled" app:menuGravity="top" />
Code language: HTML, XML (xml)

layout_fab .xml

<?xml version="1.0" encoding="utf-8"?><br><LinearLayout xmlns:android=""<br> android:layout_width="wrap_content"<br> android:layout_height="wrap_content"<br> android:orientation="vertical"><br><br> <<br> android:id="@+id/fabMain"<br> android:layout_width="wrap_content"<br> android:layout_height="wrap_content"<br> android:src="@android:drawable/ic_input_add"/><br><br></LinearLayout>
Code language: PHP (php)

Styling the Navigation Rail

There are several bundled styles that can be used to control how the Navigation Rail is displayed on the screen.


With this default style applied, the different parts of the Navigation Rail have the following attributes applied to them:



Similar to the PrimarySurface style.



In some cases, we may want our Navigation Rail to take up less width in the screen. If the default width appears to take up more space than is needed, the following style can be used to use a reduced width:



Similar to the PrimarySurface style that we previously covered, the Colored.Compact style uses the same attributes here with the small change of width:



The Widget.MaterialComponents.NavigationRailView.PrimarySurface style will automatically switch between the component’s primary-colored style in a light theme and surface-colored style in a dark theme.


Displaying Badges

Rail icons can include badges in the upper right corner of the icon. Badges convey dynamic information about the associated destination, such as counts or status.

To apply for a badge we need to utilize the getOrCreateBadge function on our navigation rail.

val inboxBadge = mainBinding.navigationRail.getOrCreateBadge(

Change the visibility of the badge using the visibility parameter.

inboxBadge.isVisible = true

Set the badge text using the number parameter.

inboxBadge.number = 10

Badge Gravity

We can control the positioning of the badge using the badgeGravity  an attribute of the BadgeDrawable.

inboxBadge.badgeGravity = BadgeDrawable.TOP_START

We can set the different badge gravity attributes.

Badge Color

We can set the colors for the badges individually, by using the backgroundColor and badgeTextColor on any of the BadgeDrawable references.

val inboxBadge = mainBinding.navigationRail.getOrCreateBadge(<em>inbox</em>)<br>inboxBadge.<em>isVisible </em>= true<br>inboxBadge.<em>number </em>= 10<br>inboxBadge.<em>badgeGravity </em>= BadgeDrawable.<em>TOP_END<br></em>inboxBadge.<em>backgroundColor </em>= Color.<em>GRAY<br></em>inboxBadge.<em>badgeTextColor </em>= Color.<em>WHITE</em>
Code language: HTML, XML (xml)

Badge Overflow

If we want to manually adjust the maximum number of characters that are to be displayed within a badge, we can do so using the maxCharacterCount attribute.

val inboxBadge = mainBinding.navigationRail.getOrCreateBadge(<em>inbox</em>) inboxBadge.<em>isVisible </em>= true inboxBadge.<em>number </em>= 56<em> </em>inboxBadge.<em>maxCharacterCount </em>= 2
Code language: HTML, XML (xml)

Badge Offset

The navigation badges are displayed outside of the icon area with enough space to not cause any overlapping. The verticalOffset and horizontalOffset attributes can be used to provide a pixel value offset for our navigation badge.

val inboxBadge = mainBinding.navigationRail.getOrCreateBadge(<em>inbox</em>) inboxBadge.<em>isVisible </em>= true inboxBadge.<em>number </em>= 56 inboxBadge.<em>badgeGravity </em>= BadgeDrawable.<em>TOP_END </em>inboxBadge.<em>backgroundColor </em>= Color.<em>GRAY </em>inboxBadge.<em>badgeTextColor </em>= Color.<em>WHITE </em>inboxBadge.<em>maxCharacterCount </em>= 2 inboxBadge.<em>verticalOffset </em>= 10 inboxBadge.<em>horizontalOffset </em>= 10
Code language: HTML, XML (xml)

Handling Item Selected

we can set an item selection listener on our Navigation Rail and use this to react to any interactions with menu items – using the ID of the menu item to handle the corresponding menu item.

mainBinding.navigationRail.setOnItemSelectedListener <strong>{ </strong>item <strong>-><br></strong><strong> </strong>when(item.<em>itemId</em>) {<br><em>inbox </em>-> {<br> // Respond to navigation item 1 click<br> true<br> }<br><em>sent </em>-> {<br> true<br> }<br><em>draft </em>-> {<br> true<br> }<br><em>trash </em>-> {<br> true<br> }<br> else -> false<br> }<br><strong>}</strong>
Code language: HTML, XML (xml)

There’s also a method for detecting when navigation items have been reselected:

mainBinding.navigationRail.setOnNavigationItemReselectedListener { item -> when(item.itemId) { -> { // Respond to navigation item 1 reselection } -> { // Respond to navigation item 2 reselection } } }
Code language: JavaScript (javascript)

That’s it. Thanks for reading.

You can download this example on Github.

Exit mobile version