Using the ActionBar in Android applications
This tutorial describes how to use the action bar in your Android applications. It is based on Eclipse 4.2 (Juno), Java 1.6 and Android 4.2 (Jelly Bean).
Table of Contents
The ActionBar (action bar) is located at the top of the activity. It can display the activity title, icon, actions which can be triggered, additional views and other interactive items. It can also be used for navigation in your application.
Older Android devices have a hardware Option button which would open a menu at the bottom of the application once pressed, i.e. the
OptionsMenu
. The action bar is superior to the OptionsMenu
, in that it is clearly visible, while the OptionsMenu
is only shown on request and the user may not recognize that options are available.The following screenshot shows the action bar of the Google+ Android application with interactive items and a navigation bar. On the top it also indicates that the user can open a navigation bar on the side of the application.
The action bar has introduced in Android 3.0. If you want to use the action bar on devices with an earlier Android release you have two popular options.
First you can use the Open Source project ActionBar Sherlock which allows you to use the ActionBar on Android devices as of Android 1.6. You find this library under the following link.
http://actionbarsherlock.com
The second option is to use the ActionBarCompat library from the Android support library v7, which supports the action bar as of Andriod 2.1. See the following link to setup the support library v7 in your project: Setting up the support library .
This description focus on the description of using the action bar without the Open Source or support library. You can easily port your application to an earlier API version using one of the different libraries.
An activity populates the action bar in its
onCreateOptionsMenu()
method. Entries in the action bar are typically called actions.The actions for the action bar are typically defined in an XML resource file. The showAsAction attribute allows you to define how the action is displayed. For example the
ifRoom
attribute defines that the action is on y displayed in the action bar if there is sufficient space available.<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/action_refresh"
android:orderInCategory="100"
android:showAsAction="always"
android:icon="@drawable/ic_action_search"
android:title="Refresh"/>
<item
android:id="@+id/action_settings"
android:title="Settings">
</item>
</menu>
The
MenuInflator
class allows to inflate actions defined in an XML file and add them to theActionBar. An instance of type MenuInflator
can get accessed via the getMenuInflator()
method in your activity. The following example code demonstrates the creation of actions.@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.mainmenu, menu);
return true;
}
To search for a menu item in a menu you can use the
findItem()
method of the Menu
class. This method allows to search by id.If an actions is selected, the
onOptionsItemSelected()
method in the corresponding activity is called. It receives the selected action as parameter. Based on this information you code can decide what to do. The usage of this method is demonstrated in the following code snippet.@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menuitem1:
Toast.makeText(this, "Menu Item 1 selected", Toast.LENGTH_SHORT)
.show();
break;
case R.id.menuitem2:
Toast.makeText(this, "Menu item 2 selected", Toast.LENGTH_SHORT)
.show();
break;
default:
break;
}
return true;
}
You can change the visibility of the action bar at runtime. The following code demonstrates that.
ActionBar actionBar = getActionBar();
actionBar.hide();
// more stuff here...
actionBar.show();
You can also change the text which is displayed alongside the application icon at runtime. The following example shows that.
ActionBar actionBar = getActionBar();
actionBar.setSubtitle("mytest");
actionBar.setTitle("vogella.com");
You also add a
Drawable
to the action bar as background via theActionBar.setBackgroundDrawable()
method.The action bar scales the image therefore it is best practice to provide a scalable drawable , e.g. an 9-patch or XML drawable.
You can also dim the software navigation button in your Android application to have more space available. If the user touches the button of the screen the navigation button are automatically shown again.
Dimming the navigation buttons is demonstrated by the following code snippet.
getWindow().
getDecorView().
setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
The following screenshots show an application with and without the navigation buttons.
The action bar shows an icon of your application, this is called the home icon. You can add an action to this icon. If you select this icon the
onOptionsItemSelected()
method will be called with the value android.R.id.home
. The recommendation is to return to the main activity in your program.// If home icon is clicked return to main Activity
case android.R.id.home:
Intent intent = new Intent(this, OverviewActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
break;
As of Android 4.1 this code is not required anymore, you can simply set the parentActivityName in the
AndroidManifest.xml
file, pointing to the parent activity.<activity
android:name="com.vogella.android.actionbar.customviews.SecondActivity"
android:label="@string/app_name"
android:parentActivityName="MainActivity">
</activity>
You can define that the action bar should be automatically split by the system if not enough space is available.
You can activate that via the
android:uiOptions="SplitActionBarWhenNarrow"
parameter in the declaration of your application or activity in the AndroidManifest.xml
file.You can also add a custom
View
to the ActionBar. For this you use the setCustomView
method for the ActionView
class. You also have to enable the display of custom views via thesetDisplayOptions()
method by passing in the ActionBar.DISPLAY_SHOW_CUSTOM
flag.For example you can define a layout file which contains a
EditText
element.<?xml version="1.0" encoding="utf-8"?>
<EditText xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/searchfield"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:inputType="textFilter" >
</EditText>
This layout can be assigned to the ActionBar via the following code. The example code allow attaches a listener to the custom view.
package com.vogella.android.actionbar.customviews;
import android.app.ActionBar;
import android.app.Activity;
import android.os.Bundle;
import android.view.KeyEvent;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
import android.widget.Toast;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActionBar actionBar = getActionBar();
// add the custom view to the action bar
actionBar.setCustomView(R.layout.actionbar_view);
EditText search = (EditText) actionBar.getCustomView().findViewById(R.id.searchfield);
search.setOnEditorActionListener(new OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId,
KeyEvent event) {
Toast.makeText(MainActivity.this, "Search triggered",
Toast.LENGTH_LONG).show();
return false;
}
});
actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM
| ActionBar.DISPLAY_SHOW_HOME);
}
}
A contextual action mode activates a temporary ActionBar that overlays the application ActionBar for the duration of a particular sub-task.
The contextual action mode is typically activated by selecting an item or by long clicking on it.
To implemented this, call the
startActionMode()
method on a View
or on your activity. This method gets an ActionMode.Callback
object which is responsible for the lifecycle of the contextual ActionBar.You could also assign a context menu to a
View
via the registerForContextMenu(view)
method. A context menu is also activated if the user "long presses" the view. TheonCreateContextMenu()
method is called every time a context menu is activated as the context menu is discarded after its usage. You should prefer the contextual action mode over the usage of context menus.An action view is a widget that appears in the action bar as a substitute for an action item's button. You can for example use this feature to replace an action item with a
ProgressBar
view. An action viewfor an action can be defined via the android:actionLayout
or android:actionViewClass
attribute to specify either a layout resource or widget class to use.This replacement is depicted in the following screenshots.
The following activity replace the icon at runtime with an
action view
which contains aProgressBar
view.package com.vogella.android.actionbar.progress;
import android.app.ActionBar;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
public class MainActivity extends Activity {
private MenuItem menuItem;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActionBar actionBar = getActionBar();
actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_HOME
| ActionBar.DISPLAY_SHOW_TITLE | ActionBar.DISPLAY_SHOW_CUSTOM);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_load:
menuItem = item;
menuItem.setActionView(R.layout.progressbar);
menuItem.expandActionView();
TestTask task = new TestTask();
task.execute("test");
break;
default:
break;
}
return true;
}
private class TestTask extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... params) {
// Simulate something long running
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(String result) {
menuItem.collapseActionView();
menuItem.setActionView(null);
}
};
}
The following code shows the layout used for the
action view
.<?xml version="1.0" encoding="utf-8"?>
<ProgressBar xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/progressBar2"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</ProgressBar>
The following code shows the XML files for the menu.
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/menu_settings"
android:orderInCategory="100"
android:showAsAction="always"
android:title="Settings"
/>
<item
android:id="@+id/menu_load"
android:icon="@drawable/navigation_refresh"
android:orderInCategory="200"
android:showAsAction="always"
android:title="Load"/>
</menu>
An ActionProvider defines rich menu interaction in a single component. It can generate action views for use in the action bar, dynamically populate submenus of a action item, and handle default action iteminvocations.
Currently the Android platform provides two ActionProvider the
MediaRouteActionProvider
and the ShareActionProvider
.The following uses the
ShareActionProvider
to demonstrate the usage of ActionProviders.This ActionProvider allows you to use share selected content using application which have registered the
Intent.ACTION_SEND
intent.To use
ShareActionProvider
you have to define a special menu entry for it and assign an intentwhich contain the sharing data to it.<?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="Share"
android:showAsAction="ifRoom"
android:actionProviderClass="android.widget.ShareActionProvider" />
<item
android:id="@+id/item1"
android:showAsAction="ifRoom"
android:title="More entries...">
</item>
</menu>
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
// Get the ActionProvider for later usage
provider = (ShareActionProvider) menu.findItem(R.id.menu_share)
.getActionProvider();
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_share:
doShare();
break;
default:
break;
}
return true;
}
public void doShare() {
// populate the share intent with data
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TEXT, "This is a message for you");
provider.setShareIntent(intent);
}
The home icon can also be used to navigate to the first activity. As of Android 4.1 you can specify this in the
AndroidManifest.xml
file with the parentActivityName
attribute on an activity.For example the
SecondActivity
activity defines the MainActivity
as home in the following snippet.<activity
android:name="SecondActivity"
android:label="@string/app_name"
android:parentActivityName="MainActivity" >
</activity>
Before Android 4.1 you had to use the
android.R.id.home
ID in theonOptionMenuItemSelected()
method and enable the selection of the home button. This is demonstrated by the following code.package com.vogella.android.actionbar.homebutton;
import android.os.Bundle;
import android.app.ActionBar;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.view.MenuItem;
public class SecondActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// enable the home button
ActionBar actionBar = getActionBar();
actionBar.setHomeButtonEnabled(true);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
break;
// Something else
case R.id.action_settings:
intent = new Intent(this, ThirdActivity.class);
startActivity(intent);
default:
break;
}
return super.onOptionsItemSelected(item);
}
}
Alternatively you can configure the home button to provide an "up" navigation in your application. The up navigation is in the opinion of the author of this text not a good practice as it is currently not very often used and hence not familiar to Android users.
A relatively new navigation pattern is the navigation drawer. The navigation drawer is a panel that displays the navigation options on the left side of the screen. It is hidden by default but can be displayed with a swipe from the left side to the right or if the user touches the app icon.
The usage of the navigation drawer in the Gmail application is depicted in the following screenshot.
The navigation drawer is part of the compatibility library v4. If you use it you create a layout with the
android.support.v4.widget.DrawerLayout
layout manager. This layout manager must contain two elements, the first is the element for the main content and the second one the container for the drawer menu. The drawer menu is typically implemented with a ListView
. Such a layout is displayed in the following snippet.<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- The main content view -->
<FrameLayout
android:id="@+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- The navigation drawer -->
<!-- should not be larger than 320 to show content -->
<ListView android:id="@+id/left_drawer"
android:layout_width="180dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:choiceMode="singleChoice"
android:divider="@android:color/transparent"
android:dividerHeight="0dp"
android:background="#111"/>
</android.support.v4.widget.DrawerLayout>
You can fill the
ListView
in your activity code and register and ListView.OnItemClickListern on the list item. In this listener you can perform the navigation action, e.g. exchange the displayed fragment.The following code demonstrate the usage. Create a layout file called fragment_layout based on the following listing. Afterwards create the OpertingSystemFragment class.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="Placeholder Text"
android:layout_gravity="center"
android:textAppearance="?android:attr/textAppearanceLarge" />
</LinearLayout>
package com.vogella.android.actionbar.navigationdrawer;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class OpertingSystemFragment extends Fragment {
public static final String ARG_OS= "OS";
private String string;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_layout, null);
TextView textView = (TextView) view.findViewById(R.id.textView1);
textView.setText(string);
return view;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
@Override
public void setArguments(Bundle args) {
string = args.getString(ARG_OS);
}
}
Afterwards add a few strings and a string array to your
values/strings.xml
file.<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Navigationdrawer</string>
<string name="action_settings">Settings</string>
<string name="action_update">Update</string>
<string name="drawer_open">Open Drawer</string>
<string name="drawer_close">Close Drawer</string>
<string name="hello_world">Hello world!</string>
<string-array name="operating_systems">
<item >Android</item>
<item >iPhone</item>
<item >Windows Mobile</item>
</string-array>
</resources>
Finally create the activity as follows.
package com.vogella.android.actionbar.navigationdrawer;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.widget.DrawerLayout;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
public class MainActivity extends Activity {
private String[] mPlanetTitles;
private DrawerLayout mDrawerLayout;
private ListView mDrawerList;
private ActionBarDrawerToggle mDrawerToggle;
private CharSequence title;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
title = getActionBar().getTitle();
mPlanetTitles = getResources().getStringArray(R.array.operating_systems);
System.out.println(mPlanetTitles.length);
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerList = (ListView) findViewById(R.id.left_drawer);
// Set the adapter for the list view
mDrawerList.setAdapter(new ArrayAdapter<String>(this,
R.layout.drawer_item,R.id.content, mPlanetTitles));
// Set the list's click listener
mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
mDrawerToggle = new ActionBarDrawerToggle(this, /* host Activity */
mDrawerLayout, /* DrawerLayout object */
R.drawable.ic_drawer, /* nav drawer icon to replace 'Up' caret */
R.string.drawer_open, /* "open drawer" description */
R.string.drawer_close /* "close drawer" description */) {
/** Called when a drawer has settled in a completely closed state. */
public void onDrawerClosed(View view) {
getActionBar().setTitle(title);
}
/** Called when a drawer has settled in a completely open state. */
public void onDrawerOpened(View drawerView) {
getActionBar().setTitle("Open Drawer");
}
};
// Set the drawer toggle as the DrawerListener
mDrawerLayout.setDrawerListener(mDrawerToggle);
getActionBar().setDisplayHomeAsUpEnabled(true);
getActionBar().setHomeButtonEnabled(true);
}
private class DrawerItemClickListener implements ListView.OnItemClickListener {
@Override
public void onItemClick(AdapterView parent, View view, int position, long id) {
selectItem(position);
}
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Sync the toggle state after onRestoreInstanceState has occurred.
mDrawerToggle.syncState();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
mDrawerToggle.onConfigurationChanged(newConfig);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Pass the event to ActionBarDrawerToggle, if it returns
// true, then it has handled the app icon touch event
if (mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
// Handle your other action bar items...
switch (item.getItemId()) {
case R.id.action_settings:
Toast.makeText(this, "Settings selected", Toast.LENGTH_LONG).show();
break;
default:
break;
}
return super.onOptionsItemSelected(item);
}
/** Swaps fragments in the main content view */
private void selectItem(int position) {
// create a new fragment and specify the planet to show based on position
Fragment fragment = new OpertingSystemFragment();
Bundle args = new Bundle();
args.putInt(OpertingSystemFragment.ARG_OS, position);
fragment.setArguments(args);
// Insert the fragment by replacing any existing fragment
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.content_frame, fragment)
.commit();
// Highlight the selected item, update the title, and close the drawer
mDrawerList.setItemChecked(position, true);
getActionBar().setTitle((mPlanetTitles[position]));
mDrawerLayout.closeDrawer(mDrawerList);
}
}
This activity uses an navigation drawer icon based on the recommendations of Google. You find a icon set from Google under the following URL: Navigation Drawer Icons .
This should be sufficient to add the navigation drawer to your application.
Fragments can also be used in combination with the ActionBar for navigation. For this your main activityneeds to implement a
TabListener
which is responsible for moving between the tabs.The ActionBar allows to add tabs to it via the
newTab()
method.The following code shows such an activity. It uses dummy activities to demonstrate the switch.
package com.vogella.android.actionbar.tabs;
import android.app.ActionBar;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class MainActivity extends FragmentActivity implements
ActionBar.TabListener {
/**
* The serialization (saved instance state) Bundle key representing the
* current tab position.
*/
private static final String STATE_SELECTED_NAVIGATION_ITEM = "selected_navigation_item";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Set up the action bar to show tabs.
final ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// for each of the sections in the app, add a tab to the action bar.
actionBar.addTab(actionBar.newTab().setText(R.string.title_section1)
.setTabListener(this));
actionBar.addTab(actionBar.newTab().setText(R.string.title_section2)
.setTabListener(this));
actionBar.addTab(actionBar.newTab().setText(R.string.title_section3)
.setTabListener(this));
}
@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
// Restore the previously serialized current tab position.
if (savedInstanceState.containsKey(STATE_SELECTED_NAVIGATION_ITEM)) {
getActionBar().setSelectedNavigationItem(savedInstanceState.getInt(STATE_SELECTED_NAVIGATION_ITEM));
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
// Serialize the current tab position.
outState.putInt(STATE_SELECTED_NAVIGATION_ITEM, getActionBar()
.getSelectedNavigationIndex());
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
@Override
public void onTabSelected(ActionBar.Tab tab,
FragmentTransaction fragmentTransaction) {
// When the given tab is selected, show the tab contents in the
// container view.
Fragment fragment = new DummySectionFragment();
Bundle args = new Bundle();
args.putInt(DummySectionFragment.ARG_SECTION_NUMBER,
tab.getPosition() + 1);
fragment.setArguments(args);
getFragmentManager().beginTransaction()
.replace(R.id.container, fragment).commit();
}
@Override
public void onTabUnselected(ActionBar.Tab tab,
FragmentTransaction fragmentTransaction) {
}
@Override
public void onTabReselected(ActionBar.Tab tab,
FragmentTransaction fragmentTransaction) {
}
/**
* A dummy fragment representing a section of the app
*/
public static class DummySectionFragment extends Fragment {
public static final String ARG_SECTION_NUMBER = "placeholder_text";
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
TextView textView = new TextView(getActivity());
textView.setGravity(Gravity.CENTER);
textView.setText(Integer.toString(getArguments().getInt(ARG_SECTION_NUMBER)));
return textView;
}
}
}
You can also use a spinner in the action bar for navigation. The following code demonstrates that.
package com.vogella.android.actionbar.spinner;
import android.app.ActionBar;
import android.app.Fragment;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
public class MainActivity extends FragmentActivity implements
ActionBar.OnNavigationListener {
/**
* The serialization (saved instance state) Bundle key representing the
* current dropdown position.
*/
private static final String STATE_SELECTED_NAVIGATION_ITEM = "selected_navigation_item";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Set up the action bar to show a dropdown list.
final ActionBar actionBar = getActionBar();
actionBar.setDisplayShowTitleEnabled(false);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
final String[] dropdownValues = getResources().getStringArray(R.array.dropdown);
// Specify a SpinnerAdapter to populate the dropdown list.
ArrayAdapter<String> adapter = new ArrayAdapter<String>(actionBar.getThemedContext(),
android.R.layout.simple_spinner_item, android.R.id.text1,
dropdownValues);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
// Set up the dropdown list navigation in the action bar.
actionBar.setListNavigationCallbacks(adapter, this);
// use getActionBar().getThemedContext() to ensure
// that the text color is always appropriate for the action bar
// background rather than the activity background.
}
@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
// Restore the previously serialized current dropdown position.
if (savedInstanceState.containsKey(STATE_SELECTED_NAVIGATION_ITEM)) {
getActionBar().setSelectedNavigationItem(savedInstanceState.getInt(STATE_SELECTED_NAVIGATION_ITEM));
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
// Serialize the current dropdown position.
outState.putInt(STATE_SELECTED_NAVIGATION_ITEM, getActionBar()
.getSelectedNavigationIndex());
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
@Override
public boolean onNavigationItemSelected(int position, long id) {
// When the given dropdown item is selected, show its contents in the
// container view.
Fragment fragment = new DummySectionFragment();
Bundle args = new Bundle();
args.putInt(DummySectionFragment.ARG_SECTION_NUMBER, position + 1);
fragment.setArguments(args);
getFragmentManager().beginTransaction()
.replace(R.id.container, fragment).commit();
return true;
}
/**
* A dummy fragment
*/
public static class DummySectionFragment extends Fragment {
public static final String ARG_SECTION_NUMBER = "placeholder_text";
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
TextView textView = new TextView(getActivity());
textView.setGravity(Gravity.CENTER);
textView.setText(Integer.toString(getArguments().getInt(ARG_SECTION_NUMBER)));
return textView;
}
}
}
This chapter will demonstrate how to create items in the ActionBar and react to the selection of the user.
It is based on the same project as the Fragment tutorial which can be found under Android Fragments tutorial . If you have already create this project you can continue to reuse it, if not the following describes the required setup to continue with this tutorial.
Use
→ → → → to create a refresh icon for your action bar. The wizard allows you to select which type of icons you want to create. Specify the name ic_refresh
for the new icon and select a corresponding entry from the Clipart.Continue to use the
com.example.android.rssfeed
project.Create a new Menu XML resource called
mainmenu.xml
. To create this XML file select your project, right click on it and select → → → → .Select the Menu option, enter mainmenu.xml as the filename and press the Finish button.
Open the
mainmenu.xml
file and select the Layout tab of the Android editor.This will create a new menu file in the
res/menu
folder of your project. Open this file and select theLayout tab of the Android editor. Via the button you can add new entries.Press the Item entry. Enter an entry similar to the following screenshot.
button and select the Add a second action to your menu. Use
Refresh
as the title attribute and menuitem_refresh
as the ID attribute.Assign a fitting icon to it for example an icon which you downloaded earlier in this exercise. Copy the icon you want to use into
/res/drawable-mdpi
folder. Make sure that the filename does not has any special character and that you only copy the icon which you want to use, not all of them.Add a second entry to the menu with the ID attribute set to "@+id/action_settings", and the Titleattribute set to "Setting". Set the android:showAsAction to
never
.The resulting XML will look like the following code. Please note that your drawable entry is properly different.
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/action_refresh"
android:orderInCategory="100"
android:showAsAction="always"
android:icon="@drawable/ic_action_refresh"
android:title="Refresh"/>
<item
android:id="@+id/action_settings"
android:title="Settings"
android:showAsAction="never"
>
</item>
</menu>
Change your
RssfeedActivity
class to the following code to use this XML file.package com.example.android.rssfeed;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
public class RssfeedActivity extends Activity implements
MyListFragment.OnItemSelectedListener {
// Unchanged
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_rssfeed);
}
//NEW
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.mainmenu, menu);
return true;
}
//NEW
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_refresh:
Toast.makeText(this, "Action refresh selected", Toast.LENGTH_SHORT)
.show();
break;
case R.id.action_settings:
Toast.makeText(this, "Action Settings selected", Toast.LENGTH_SHORT)
.show();
break;
default:
break;
}
return true;
}
// Other methods which this class implements
}
Run your application. As there is enough space in the ActionBar otherwise you may see the Overflow menu or you have to use the
menu button on your phone. If you select one item, you should see a small info message.Create a project called de.vogella.android.socialapp with the activity called OverviewActivity.
Add a
EditText
element your main.xml
layout file.<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<EditText
android:id="@+id/myView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10" >
<requestFocus />
</EditText>
</LinearLayout>
Create a new menu XML resource with the
contextual.xml
file name.<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/toast"
android:title="Toast">
</item>
</menu>
Change your activity to the following.
package de.vogella.android.socialapp;
import android.app.Activity;
import android.os.Bundle;
import android.view.ActionMode;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.Toast;
public class OverviewActivity extends Activity {
protected Object mActionMode;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// define the contextual action mode
View view = findViewById(R.id.myView);
view.setOnLongClickListener(new View.OnLongClickListener() {
// called when the user long-clicks on someView
public boolean onLongClick(View view) {
if (mActionMode != null) {
return false;
}
// start the CAB using the ActionMode.Callback defined above
mActionMode = OverviewActivity.this
.startActionMode(mActionModeCallback);
view.setSelected(true);
return true;
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.mainmenu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
Toast.makeText(this, "Just a test", Toast.LENGTH_SHORT).show();
return true;
}
private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() {
// Called when the action mode is created; startActionMode() was called
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
// inflate a menu resource providing context menu items
MenuInflater inflater = mode.getMenuInflater();
// assumes that you have "contexual.xml" menu resources
inflater.inflate(R.menu.contextual, menu);
return true;
}
// called each time the action mode is shown. Always called after
// onCreateActionMode, but
// may be called multiple times if the mode is invalidated.
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false; // Return false if nothing is done
}
// called when the user selects a contextual menu item
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.toast:
Toast.makeText(OverviewActivity.this, "Selected menu",
Toast.LENGTH_LONG).show();
mode.finish(); // Action picked, so close the CAB
return true;
default:
return false;
}
}
// called when the user exits the action mode
public void onDestroyActionMode(ActionMode mode) {
mActionMode = null;
}
};
}
If you run this example and long press the
EditText
widget, your contextual ActionBar is displayed.
No comments:
Post a Comment