available to the user without searching through option menus or context menus.
An action bar is owned by an activity and follows its lifecycle.
An action bar can take one of three forms: tabbed action bar, list
action bar, or standard action bar. You see how these various action
bars look and behave in each of the modes.
ou see how to place a custom search widget in the action bar
provides user actions and navigation modes
Beginning with Android 3.0 (API level 11), the action bar is included in all activities that use the Theme.Holo
theme (or one of its descendants), which is the default theme when either thetargetSdkVersion
or minSdkVersion
attribute is set to "11"
or greater.
If you don't want the action bar for a particular activity, set the activity theme to Theme.Holo.NoActionBar
. For example:
<activity android:theme="@android:style/Theme.Holo.NoActionBar">
You can also hide the action bar at runtime by calling hide()
. For example:
ActionBar actionBar = getActionBar()
;
actionBar.hide();
When the action bar hides, the system adjusts your activity layout to fill all the screen space now available. You can bring the action bar back with show()
.
your activity regularly hides and shows the action bar (such as in the Android Gallery app), you might want to use overlay mode. Overlay mode draws the action bar on top of your activity layout rather than in its own area of the screen
To enable overlay mode, create a theme for your activity and setandroid:windowActionBarOverlay
to true
.
In the XML file, you can request a menu item to appear as an action item by declaringandroid:showAsAction="ifRoom"
for the <item>
element. This way, the menu item appears in the action bar for quick access only if there is room available. If there's not enough room, the item appears in the overflow menu.
menu item supplies both a title and an icon if you want to display the text title, add "withText"
to theandroid:showAsAction
attribute.
However the activity gets a chance to handle the event first, so the system calls onOptionsItemSelected()
on the activity before calling the same callback for the fragment.
Using the App Icon for Navigation
When the user touches the icon, the system calls your activity'sonOptionsItemSelected()
method with the android.R.id.home
ID. In response, you should either start the home activity or take the user one step up in your application's structural hierarchy.
If you respond to the application icon by returning to the home activity, you should include the FLAG_ACTIVITY_CLEAR_TOP
flag in the Intent
. With this flag,
In case the user can enter the current activity from another application, you might also want to add theFLAG_ACTIVITY_NEW_TASK
flag. This flag ensures that, when the user navigates either "home" or "up", the new activity is not added to the current task, but instead started in a task that belongs to your application
So if your activity accepts intents from other applications (it declares any generic intent filters), you should usually add theFLAG_ACTIVITY_NEW_TASK
flag to the intent:
To declare an action view for an item in your menu resource, use either the android:actionLayout
orandroid:actionViewClass
attribute to specify either a layout resource or widget class to use, respectively. For example:
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/menu_search" android:title="@string/menu_search" android:icon="@drawable/ic_menu_search" android:showAsAction="ifRoom|collapseActionView" android:actionViewClass="android.widget.SearchView" /> </menu>Notice that the
android:showAsAction
attribute also includes
"collapseActionView"
. This is optional and declares that the action view should be collapsed into a button. When the user selects the button, the action view expands.
If you need to update your activity based on the visibility of your action view, you can receive callbacks when it's expanded and collapsed by defining an OnActionExpandListener
and registering it withsetOnActionExpandListener()
. For example:
@Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.options, menu); MenuItem menuItem = menu.findItem(R.id.actionItem); ... menuItem.setOnActionExpandListener(new OnActionExpandListener() { @Override public boolean onMenuItemActionCollapse(MenuItem item) { // Do something when collapsed return true; // Return true to collapse action view } @Override public boolean onMenuItemActionExpand(MenuItem item) { // Do something when expanded return true; // Return true to expand action view } }); }
Adding an Action Provider
the ShareActionProvider
is an extension ofActionProvider
that facilitates a “share" action by showing a list of available share targets from the action bar.
To declare an action provider for an action item, define theandroid:actionProviderClass
attribute for the appropriate the <item>
element in your menu resource, using the fully-qualified class name of the action provider. For example:
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/menu_share" android:title="@string/share" android:showAsAction="ifRoom" android:actionProviderClass="android.widget.ShareActionProvider" /> ... </menu>Creating a custom action provider
To create your own, simply extend the
ActionProvider
class and implement its callback methods as appropriate. Most importantly, you should implement the following:
-
This constructor passes you the application
Context
, which you should save in a member field to use in the other callback methods. -
This is where you define the action view for the item. Use the
Context
acquired from the constructor to instantiate aLayoutInflater
and inflate your action view layout from an XML resource, then hook up event listeners. For example:public View onCreateActionView() { // Inflate the action view to be shown on the action bar. LayoutInflater layoutInflater = LayoutInflater.from(mContext); View view = layoutInflater.inflate(R.layout.action_provider, null); ImageButton button = (ImageButton) view.findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // Do something... } }); return view; }
-
The system calls this when the menu item is selected from the overflow menu and the action provider should perform a default action for the menu item.
However, if your action provider provides a submenu, through the
onPrepareSubMenu()
callback, then the submenu appears even when the menu item is in the overflow menu. Thus,onPerformDefaultAction()
is never called when there is a submenu.Note: An activity or a fragment that implements
onOptionsItemSelected()
can override the action provider's default behavior by handling the item-selected event (and returning true), in which case, the system does not callonPerformDefaultAction()
.
ActionProvider()
onCreateActionView()
onPerformDefaultAction()
Adding Navigation Tabs
TabWidget
), because the system adapts the action bar tabs for different screen sizes—placing them in the main action bar when the screen is sufficiently wide, or in a separate bar (known as the "stacked action bar") when the screen is too narrow, as shown in figures 9 and 10.@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Notice that setContentView() is not used, because we use the root // android.R.id.content as the container for each fragment // setup action bar for tabs ActionBar actionBar = getActionBar(); actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); actionBar.setDisplayShowTitleEnabled(false); Tab tab = actionBar.newTab() .setText(R.string.artist) .setTabListener(new TabListener<ArtistFragment>( this, "artist", ArtistFragment.class)); actionBar.addTab(tab); tab = actionBar.newTab() .setText(R.string.album) .setTabListener(new TabListener<AlbumFragment>( this, "album", AlbumFragment.class)); actionBar.addTab(tab); }
public static class TabListener<T extends Fragment> implements ActionBar.TabListener {
private Fragment mFragment;
private final Activity mActivity;
private final String mTag;
private final Class<T> mClass;
/** Constructor used each time a new tab is created.
* @param activity The host Activity, used to instantiate the fragment
* @param tag The identifier tag for the fragment
* @param clz The fragment's Class, used to instantiate the fragment
*/
public TabListener(Activity activity, String tag, Class<T> clz) {
mActivity = activity;
mTag = tag;
mClass = clz;
}
/* The following are each of the ActionBar.TabListener
callbacks */
public void onTabSelected(Tab tab, FragmentTransaction ft) {
// Check if the fragment is already initialized
if (mFragment == null) {
// If not, instantiate and add it to the activity
mFragment = Fragment.instantiate(mActivity, mClass.getName());
ft.add(android.R.id.content, mFragment, mTag);
} else {
// If it exists, simply attach it in order to show it
ft.attach(mFragment);
}
}
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
if (mFragment != null) {
// Detach the fragment, because another one is being attached
ft.detach(mFragment);
}
}
public void onTabReselected(Tab tab, FragmentTransaction ft) {
// User selected the already selected tab. Usually do nothing.
}
}
Adding Drop-down Navigation
The basic procedure to enable drop-down navigation is:
- Create a
SpinnerAdapter
that provides the list of selectable items for the drop-down and the layout to use when drawing each item in the list. - Implement
ActionBar.OnNavigationListener
to define the behavior that occurs when the user selects an item from the list. - Enable navigation mode for the action bar with
setNavigationMode()
. For example:ActionBar actionBar = getActionBar(); actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
Note: You should perform this during your activity's
onCreate()
method. - Set the callback for the drop-down list with
setListNavigationCallbacks()
. For example:actionBar.setListNavigationCallbacks(mSpinnerAdapter, mNavigationCallback);
is an adapter that provides data for a spinner widget, such as the drop-down list in the action bar.
SpinnerAdapterSpinnerAdapter
is an interface that you can implement, but Android includes some useful implementations that you can extend, such as ArrayAdapter
and SimpleCursorAdapter
. For example, here's an easy way to create a SpinnerAdapter
by using ArrayAdapter
implementation, which uses a string array as the data source:
SpinnerAdapter mSpinnerAdapter = ArrayAdapter.createFromResource(this, R.array.action_list, android.R.layout.simple_spinner_dropdown_item);
The createFromResource()
method takes three parameters: the application Context
, the resource ID for the string array, and the layout to use for each list item.
A string array defined in a resource looks like this:
<?xml version="1.0" encoding="utf-8"?> <resources> <string-array name="action_list"> <item>Mercury</item> <item>Venus</item> <item>Earth</item> </string-array> </pre>
The ArrayAdapter
returned by createFromResource()
is complete and ready for you to pass it tosetListNavigationCallbacks()
(in step 4 from above). Before you do, though, you need to create theOnNavigationListener
.
Your implementation of ActionBar.OnNavigationListener
is where you handle fragment changes or other modifications to your activity when the user selects an item from the drop-down list. There's only one callback method to implement in the listener: onNavigationItemSelected()
.
The onNavigationItemSelected()
method receives the position of the item in the list and a unique item ID provided by the SpinnerAdapter
.
Here's an example that instantiates an anonymous implementation of OnNavigationListener
, which inserts a Fragment
into the layout container identified by R.id.fragment_container
:
mOnNavigationListener = new OnNavigationListener() { // Get the same strings provided for the drop-down's ArrayAdapter String[] strings = getResources().getStringArray(R.array.action_list); @Override public boolean onNavigationItemSelected(int position, long itemId) { // Create new fragment from our own Fragment class ListContentFragment newFragment = new ListContentFragment(); FragmentTransaction ft = openFragmentTransaction(); // Replace whatever is in the fragment container with this fragment // and give the fragment a tag name equal to the string at the position selected ft.replace(R.id.fragment_container, newFragment, strings[position]); // Apply changes ft.commit(); return true; } };
This instance of OnNavigationListener
is complete and you can now callsetListNavigationCallbacks()
(in step 4), passing the ArrayAdapter
and this OnNavigationListener
.
In this example, when the user selects an item from the drop-down list, a fragment is added to the layout (replacing the current fragment in the R.id.fragment_container
view). The fragment added is given a tag that uniquely identifies it, which is the same string used to identify the fragment in the drop-down list.
Here's a look at the ListContentFragment
class that defines each fragment in this example:
public class ListContentFragment extends Fragment { private String mText; @Override public void onAttach(Activity activity) { // This is the first callback received; here we can set the text for // the fragment as defined by the tag specified during the fragment transaction super.onAttach(activity); mText = getTag(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // This is called to define the layout for the fragment; // we just create a TextView and set its text to be the fragment tag TextView text = new TextView(getActivity()); text.setText(mText); return text; } }