Beginning at API Level 11 (Android 3.0), Android moved away from using traditional menus to instead use the ActionBar. The ActionBar provides action items that are a combination of button-based actions that appear directly on the ActionBar and menu-based actions that appear in a drop-down list when the user taps on the Action overflow button. The following screenshot shows the available ActionBar actions:

What many developers don't realize is that the button-based and menu-based actions are just a small subset of what the ActionBar actually does. The ActionBar now serves as a central point for many navigation-related behaviors. Two of these behaviors are tied directly to fragments: tab navigation and drop-down navigation.
To incorporate the ActionBar in applications targeting versions of Android with an API Level below 11, use the ActionBarCompat class available in the Android Support Library. For more information on the ActionBarCompat class visit http://bit.ly/ActionBarCompat.
Tabs are an effective navigation model. They're well understood by users, and make moving between screens within an app easy. Unlike swipe navigation that requires the user to move through screens in order, tab navigation allows the user to move from one screen to another in any order they like. Android has supported tab navigation since the original release of the platform. Historically, the challenge of implementing tab navigation was that it was unrelated to other navigation models and required using a special activity class and other tab-specific classes. With the ActionBar, this is all changed. Now, tab navigation is just another use of the common fragment programming model.
The ActionBar allows us to associate an instance of a fragment derived class with each tab. The following screenshot shows the top portion of the screen of two different devices, with the ActionBar displaying tabs:

Notice that the ActionBar automatically adapts the way the tabs are displayed in response to the available screen space. On the narrower device, the ActionBar places the tabs under the main portion of the ActionBar, whereas on the wider device with more horizontal screen space, the tabs appear directly on the main portion of the ActionBar.
The ActionBar manages all the heavy lifting when it comes to implementing tab navigation. It draws the tabs, indicates which tab is currently selected, and even takes care of beginning and committing a fragment transaction. All we have to do is handle which fragment is visible, based on the tab currently selected. We do this by providing an implementation of the ActionBar.TabListener interface for each tab. The following code shows the declaration of a class implementing the interface:
public class SimpleTabListener implements ActionBar.TabListener {
boolean mFirstSelect = true;
Fragment mFragment;
public SimpleTabListener(Fragment fragment) {
mFragment = fragment;
}
// Other members elided for clarity
}Our TabListener implementation has two member variables. The boolean member variable, mFirstSelect, is used to control the special handling that's necessary the first time the fragment managed by our SimpleTabListener class is selected. The other member variable, mFragment, holds a reference to the fragment that is managed by the TabListener instance, which is set in our SimpleTabListener constructor.
The first TabListener interface method we'll implement is the onTabSelected method. As the method name indicates, onTabSelected is called each time the tab associated with this TabListener instance becomes the selected tab. The onTabSelected method is implemented as shown in the following code:
public void onTabSelected(
ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
if (mFirstSelect) {
fragmentTransaction.add(android.R.id.content, mFragment);
mFirstSelect = false;
}
else
fragmentTransaction.attach(mFragment);
}Two parameters are passed to the onTabSelected method. The first parameter is a reference to the tab instance that is associated with our TabListener implementation. The second parameter is the FragmentTransaction instance that is managed by the ActionBar. The ActionBar starts this transaction, and will commit the transaction after onTabSelected returns.
The first time the onTabSelected method is called, we use the passed FragmentTransaction instance to add our fragment to the display using the add method. As we discussed in the previous chapter, the first parameter to the add method is the ID of the view group under which we want the fragment to be placed. Just as when we're managing FragmentsTransaction ourselves, this can be any valid view group within the activity layout. In the previous code, we're using a special ID value that is predefined by Android, android.R.id.content. The android.R.id.content ID value indicates that we want the fragment to occupy the entire content area of the activity rather than be placed under a specific view group within the activity.
We only use the add method the first time the tab is selected; every time thereafter, we use the FragmentTransaction class' attach method. We'll talk more about that in a moment.
The next TabListener interface method we'll implement is the onTabUnselected method, which is shown in the following code:
public void onTabUnselected(
ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
fragmentTransaction.detach(mFragment);
}The onTabUnselected method receives the same parameters as the onTabSelected method. Our implementation of this method is simple, having only one line in which we call the FragmentTransaction class' detach method.
The
detach method call in the onTabUnselected method works together with the attach method call in the onTabSelected method. Once the fragment is initially added to the activity, as we do in the onTabSelected method the first time the fragment is shown, we can then call the detach method to tear down the fragment's view hierarchy, but leave the fragment associated with the activity. When we call the attach method within the onTabSelected method, the next time the user selects the tab for the fragment, the fragment's view hierarchy is rebuilt at the same place within the activity where the fragment was originally added.
This technique of calling the detach and attach methods allows us to manage the fragments more efficiently. When we call the detach method, the fragment's onDestroyView method is called, but not the onDestroy method. When we later call the attach method, the fragment's onCreateView method is called, but not the onCreate method, because the fragment does not need to be fully recreated just its view hierarchy needs to be recreated.
There is a bit of potential confusion related to method names that we need to be aware of. When a fragment instance is passed to the FragmentTransaction class' detach method, the Fragment class' onDetach method does not get called. This is because the detach method tears down the fragment's view hierarchy but leaves the fragment associated with the activity; the fragment remains attached. Similarly, when a fragment instance is passed to the FragmentTransaction class' attach method, the Fragment class' onAttach method does not get called because the fragment is already attached to the activity. This is certainly a little confusing, but it ultimately comes down to a bad choice of method names on the part of the API designers rather than being a technical inconsistency.
The last method on the TabListener interface, onTabReselected, is called in scenarios where the user taps the tab that is already selected; in other words, the user reselects the same tab. In most cases, this method can be left empty, as shown in the following code:
public void onTabReselected(
ActionBar.Tab tab, FragmentTransaction fragmentTransaction) { }With our TabListener implementation in place, we can now connect the fragments to the tabs. We'll do this in the activity's onCreate method, which is shown in the following code:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Put ActionBar in Tab mode
ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Create the first tab
Fragment firstFragment = new FirstFragment();
ActionBar.TabListener firstListener =
new SimpleTabListener(firstFragment);
ActionBar.Tab firstTab = actionBar.newTab()
.setText("First")
.setTabListener(firstListener);
actionBar.addTab(firstTab);
// Create the second tab
Fragment secondFragment = new SecondFragment();
ActionBar.TabListener secondListener =
new SimpleTabListener(secondFragment);
ActionBar.Tab secondTab = actionBar.newTab()
.setText("Second")
.setTabListener(secondListener);
actionBar.addTab(secondTab);
}In our onCreate implementation, we start by getting a reference to the ActionBar, and putting the ActionBar into tab navigation mode. This step is essential; without it, the tabs we add will never be visible.
For the first tab, we create the fragment that will serve as the body of the tab. This can be virtually any fragment derived class. We then associate our TabListener implementation with the fragment. With the fragment and TabListener implementation in place, we create a new ActionBar.Tab instance with the call to the newTab method, we then set the text that will display within the tab, and associate our TabListener instance with the tab. Finally, we add the ActionBar.Tab instance to the ActionBar with the addTab method. We then repeat those steps for the second tab.
With that, we now have tab navigation implemented in our application. Using this technique, we're able to leverage all the capabilities of fragments and implement tab-based navigation in a way that is consistent with other ways we use fragments.
One thing that may appear unusual about our onCreate method implementation is the absence of a call to the setContentView method. In this case, we don't need to associate a layout resource with the activity, because we're using the special-purpose android.R.id.content resource ID when we call the add method in our onTabSelected implementation. As we mentioned earlier, the resource ID android.R.id.content indicates that the fragment occupies the entire content area. If we wanted the tab to control the display of a fragment within some view group, we would call setContentView with a resource containing the desired layout. We would then use the ID of the view group within that layout in our call to the add method.
Tab navigation works well when an app has just a few predictable screens, but quickly becomes cluttered if there are a large number of screens. For those scenarios where an app has a large number of screens or possibly the number of screens might even change over time, drop-down list navigation provides a much better solution than tabs. Drop-down list navigation places a drop-down list on the ActionBar containing the list of available screen names. When the user chooses a screen name from the list, the app immediately displays the corresponding screen.
Probably the most familiar use of this navigation model on Android is the Android e-mail app, which is shown in the following screenshot:

In the Android e-mail app, the list of different available e-mail folder screens appears in the drop-down list. Tapping the ActionBar displays the list and then selecting the screen name from the list immediately displays the screen.
Incorporating drop-down list navigation in our apps is very simple.
Unlike tab navigation, where the ActionBar takes a very active role in managing the transition from one fragment to another, in drop-down list navigation the ActionBar takes a much more hands-off approach. Basically, the ActionBar simply notifies the app that the selection has changed, and leaves the details of switching fragments up to the app. To handle the notification we need to provide an implementation of the ActionBar.OnNavigationListener interface. The implementation declaration is shown in the following code:
public class SimpleNavigationListener
implements ActionBar.OnNavigationListener {
FragmentManager mFragmentManager;
public SimpleNavigationListener(FragmentManager fm) {
mFragmentManager = fm;
}
// Other members elided for clarity
}Our ActionBar.OnNavigationListener implementation has a single member variable, mFragmentManager, to hold a reference to the activity's FragmentManager instance. The FragmentManager reference is passed to our class in the constructor.
Unlike in tab navigation where each tab instance is managed by a separate TabListener instance, in drop-down list navigation a single OnNavigationListener implementation handles all the selections. The OnNavigationListener interface's only method, onNavigationItemSelected, is called each time the selection changes and is responsible for taking care of displaying the appropriate fragment, as shown in the following implementation:
public boolean onNavigationItemSelected(
int itemPosition, long itemId) {
Fragment fragment = null;
// Create an instance of the appropriate Fragment
switch (itemPosition) {
case 0:
fragment = new FirstFragment();
break;
case 1:
fragment = new SecondFragment();
break;
case 2:
fragment = new ThirdFragment();
break;
}
// Replace the currently visible fragment with the new one
if (fragment != null) {
FragmentTransaction ft = mFragmentManager.beginTransaction();
ft.replace(android.R.id.content, fragment);
ft.commit();
}
return true;
}We receive the zero-based index of the selection as the first parameter, itemPosition. We'll be populating the list of screen names from a simple String array so the second parameter, itemId, does not have value to us. If we were to use a more structured data source, the itemId parameter would contain the ID of the selection.
Using a switch statement, we create an instance of the appropriate fragment derived class. Once we have the fragment instance, we replace the currently visible fragment with the one we just created. We again use the layout resource ID, android.R.id.content, indicating that the fragment occupies the entire content area of the activity. Just as with tab navigation, we could instead use the ID value of a view group within the activity's layout, if we prefer.
Notice that we're explicitly creating and committing the FragmentTransaction instance in our code. This is another important difference from how tab navigation is managed; we're responsible for all the details. The test that the local variable, fragment, is not null is just a sanity check. As long as we don't display more than three values for the user to select from, the fragment variable will never be null.
Providing a method return value of true simply indicates that we have handled the event.
We now need to provide the ActionBar with the information necessary to display the list of navigation choices. We do that in the activity's onCreate method, which is shown in the following code:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Put the ActionBar in the right mode and clear any clutter
ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
actionBar.setDisplayShowTitleEnabled(false);
// Get the list of display values and wrap in an adapter
String[] screenNames =getResources().getStringArray(R.array.screen_names);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, screenNames);
// Create the Listener and associate with the ActionBar
ActionBar.OnNavigationListener listener =new SimpleNavigationListener(getFragmentManager());
actionBar.setListNavigationCallbacks(adapter, listener);
}The first step in setting up drop-down list navigation is to put the ActionBar into list navigation mode with the call to the setNavigationMode method. The drop-down list containing the screen choices appears directly on the ActionBar, which can be problematic if the ActionBar attempts to show both the drop-down list and the activity title text. To make room for the list, we call the setDisplayShowTitleEnabled method with a value of false so that the title doesn't display.
We retrieve the list of display values from the array resource, which is a regular String array. We wrap the String array in an instance of the ArrayAdapter class just as we would if we were planning to associate the String array with a standard ListView instance appearing within a layout definition for an activity. The String array resource definition appears as shown in the following XML code:
<string-array name="screen_names"> <item>First View</item> <item>Second View</item> <item>Third View</item> </string-array>
We then create an instance of SimpleNavigationListener, which we had defined earlier. Finally, we set the list of displayed screen names and the screen selection handler by calling the setListNavigationCallbacks method to associate the ArrayAdapter and SimpleNavigationListener implementations with the ActionBar.
With that we have drop-down navigation fully implemented. When we run the application, the list of screen selections will appear as shown in the following screenshot. The ActionBar initially appears as shown on the left-hand side in the following screenshot, with the currently selected screen's name displayed. When the user taps on the currently selected screen name, the list expands to display the list of available screen names as shown on the right-hand side of the following screenshot. With the list expanded, the user can easily jump directly to any of the available screens by tapping on the desired screen's name within the list.

If we're working with Android Studio, we can create a project that supports drop-down list navigation directly from the New Project wizard by selecting Dropdown as the Navigation Type, similar to the way we created a project with swipe navigation. The resulting project will contain a stubbed-out ActionBar.OnNavigationListener implementation along with the code within the activity to put the ActionBar into drop-down list navigation mode, and associate the ActionBar.OnNavigationListener implementation with the ActionBar.