Android L
Action bar
Navigation modes
Deprecation
Android development

Action bar navigation modes are deprecated in Android L

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

With the release of Android L (Lollipop), Google deprecated Action Bar navigation modes as part of the broader shift toward Material Design. Developers who relied on tab and drop-down navigation modes in the Action Bar needed to migrate to modern alternatives like Toolbar, TabLayout, and the Navigation Component. This article covers why the deprecation happened, what replaced these modes, and how to migrate existing code.

Why Action Bar Navigation Modes Were Deprecated

Action Bar was introduced in Android 3.0 (Honeycomb) and provided built-in navigation modes including tabs (NAVIGATION_MODE_TABS) and drop-down lists (NAVIGATION_MODE_LIST). While convenient, these modes had several limitations that conflicted with the goals of Material Design.

The tab and list modes were tightly coupled to the Action Bar itself, making it difficult to customize their appearance or position them independently. On smaller screens, tabs would collapse into a stacked bar, consuming valuable vertical space. The rigid API also prevented developers from implementing fluid transitions and animations that Material Design requires.

Google's solution was to deprecate these navigation modes entirely and provide standalone components that offer greater flexibility. The Toolbar widget replaced the Action Bar as the primary app bar, while TabLayout from the Design Support Library became the recommended way to implement tabbed navigation.

Migrating from Action Bar Tabs to Toolbar and TabLayout

The most common migration path involves replacing Action Bar tabs with a combination of Toolbar, TabLayout, and ViewPager2. Here is a complete example.

First, update your theme to use NoActionBar so the system does not create a default Action Bar:

xml
1<style name="AppTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
2    <item name="colorPrimary">@color/primary</item>
3    <item name="colorPrimaryVariant">@color/primary_dark</item>
4</style>

Next, define your layout with a Toolbar and TabLayout above a ViewPager2:

xml
1<LinearLayout
2    xmlns:android="http://schemas.android.com/apk/res/android"
3    xmlns:app="http://schemas.android.com/apk/res-auto"
4    android:layout_width="match_parent"
5    android:layout_height="match_parent"
6    android:orientation="vertical">
7
8    <com.google.android.material.appbar.AppBarLayout
9        android:layout_width="match_parent"
10        android:layout_height="wrap_content">
11
12        <androidx.appcompat.widget.Toolbar
13            android:id="@+id/toolbar"
14            android:layout_width="match_parent"
15            android:layout_height="?attr/actionBarSize" />
16
17        <com.google.android.material.tabs.TabLayout
18            android:id="@+id/tab_layout"
19            android:layout_width="match_parent"
20            android:layout_height="wrap_content"
21            app:tabMode="fixed" />
22
23    </com.google.android.material.appbar.AppBarLayout>
24
25    <androidx.viewpager2.widget.ViewPager2
26        android:id="@+id/view_pager"
27        android:layout_width="match_parent"
28        android:layout_height="match_parent" />
29
30</LinearLayout>

Then wire everything together in your Activity:

kotlin
1class MainActivity : AppCompatActivity() {
2    override fun onCreate(savedInstanceState: Bundle?) {
3        super.onCreate(savedInstanceState)
4        setContentView(R.layout.activity_main)
5
6        val toolbar = findViewById<Toolbar>(R.id.toolbar)
7        setSupportActionBar(toolbar)
8
9        val viewPager = findViewById<ViewPager2>(R.id.view_pager)
10        viewPager.adapter = SectionsPagerAdapter(this)
11
12        val tabLayout = findViewById<TabLayout>(R.id.tab_layout)
13        TabLayoutMediator(tabLayout, viewPager) { tab, position ->
14            tab.text = when (position) {
15                0 -> "Home"
16                1 -> "Profile"
17                2 -> "Settings"
18                else -> "Tab $position"
19            }
20        }.attach()
21    }
22}

Migrating Drop-Down Navigation to a Spinner in Toolbar

For apps that used NAVIGATION_MODE_LIST, the replacement is a Spinner placed directly inside the Toolbar:

kotlin
1val toolbar = findViewById<Toolbar>(R.id.toolbar)
2setSupportActionBar(toolbar)
3supportActionBar?.setDisplayShowTitleEnabled(false)
4
5val spinner = Spinner(supportActionBar?.themedContext ?: this)
6val adapter = ArrayAdapter.createFromResource(
7    this, R.array.nav_items, android.R.layout.simple_spinner_dropdown_item
8)
9spinner.adapter = adapter
10spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
11    override fun onItemSelected(parent: AdapterView<*>, view: View?, pos: Int, id: Long) {
12        // Handle navigation selection
13    }
14    override fun onNothingSelected(parent: AdapterView<*>) {}
15}
16toolbar.addView(spinner)

Using the Jetpack Navigation Component

For new projects, the Jetpack Navigation Component is the recommended approach. It provides a declarative way to define navigation graphs and handles fragment transactions, back stack management, and deep linking automatically.

kotlin
1// In your Activity
2val navController = findNavController(R.id.nav_host_fragment)
3val appBarConfig = AppBarConfiguration(navController.graph)
4toolbar.setupWithNavController(navController, appBarConfig)

The Navigation Component pairs well with BottomNavigationView for bottom tab navigation, which has largely replaced top-level Action Bar tabs in modern Android apps.

Common Pitfalls

Forgetting to switch the app theme to NoActionBar is a frequent mistake. If you use both a Toolbar and a default Action Bar, the app will crash with an IllegalStateException because it tries to set two action bars.

Another common issue is not using TabLayoutMediator to connect TabLayout with ViewPager2. Without the mediator, tabs will not update when the user swipes between pages, and tapping a tab will not scroll the pager.

When migrating legacy code, watch for direct references to getActionBar().setNavigationMode(). These calls will still compile against newer SDK versions but will have no effect, leading to confusing behavior where the navigation simply disappears.

Summary

Action Bar navigation modes were deprecated in Android L because they were inflexible and inconsistent with Material Design principles. The modern replacements, Toolbar with TabLayout and ViewPager2, provide full control over appearance and behavior. For new projects, the Jetpack Navigation Component offers the most maintainable approach. When migrating, switch your theme to NoActionBar, replace tab logic with TabLayoutMediator, and remove all calls to the deprecated setNavigationMode API.


Course illustration
Course illustration

All Rights Reserved.