Using the Android action bar (ActionBar) – Tutorial


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).


1. Introduction to the ActionBar

1.1. What is the ActionBar?

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.

1.2. Example

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.

ActionBar Screenshot

1.3. Using the ActionBar on older devices

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.

2. Using the ActionBar

2.1. Creating actions in the ActionBar

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 the

ActionBar

. 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;
}

Tip

While you can define the actions also in your source code, it is good practice to do this via XML files, as this results in less boilerplate code.

2.2. Search an action in the action bar

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.

2.3. Reacting to actions selection

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;
}

2.4. Changing the menu

The

onCreateOptionsMenu()

method is only called once. If you want to change the menu later you have to call the

invalidateOptionsMenu()

method. Afterwards this

onCreateOptionsMenu()

method is called again.

3. Customizing the ActionBar

3.1. Adjusting the ActionBar

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"

);

3.2. Assigning a Drawable

You also add a

Drawable

to the action bar as background via the

ActionBar.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.

Tip

As of Android 4.2 the background of the action bar can also be an animated via an

AnimationDrawable

.

3.3. Dimming the navigation buttons

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.





4.  Further options for the ActionBar

4.1. Using the home icon

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>

4.2. Enabling the split action bar

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.

5.  Making the ActioinBar dynamic

5.1. Custom Views in the ActionBar

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 the

setDisplayOptions()

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);
}

}

5.2. Contextual ActionBar

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. The

onCreateContextMenu()

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.

5.3. Action view

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 view

for 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.

Before activating the ActionView
ActionViews running

The following

activity

replace the icon at runtime with an

action view

which contains a

ProgressBar

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>

6. ActionProvider

6.1. Overview of ActionProvider

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 item

invocations.

Currently the Android platform provides two ActionProvider the

MediaRouteActionProvider

and the

ShareActionProvider

.

6.2. Example: usage of 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

intent

which 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);
}

7. Navigation with the action bar

7.1. Navigation via the home icon

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 the

onOptionMenuItemSelected()

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.

7.2. Navigation Drawer

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.

Navigation Drawer in Gmail

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.

Tip

The usage of the navigation drawer is currently very popular for Android application. It seem that this navigation pattern is well accepted by end users.

7.3. Tab navigation

Fragments can also be used in combination with the

ActionBar

for navigation. For this your main

activity

needs 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; } } }

7.4. Dropdown menu navigation

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; } } }

8. Exercise: ActionBar

8.1. Project

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.

8.2. Create Project

Create a new Android project with the following data.


Table 1. Android project

Property Value
Application Name RSS Reader
Project Name com.example.android.rssfeed
Package name com.example.android.rssfeed
Template BlankActivity
Activity RssfeedActivity
Layout activity_rssfeed

9. Exercise: Add action bar to your application

9.1. Create icon for the ActionBar

Use

File

?

New

?

Other…

?

Android

?

Android Icon Set

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.

Note

The Android design page also provides prepared icons for the ActionBar. You find the downloads on the following webpage.

http:

//developer.android.com/design/downloads/index.html 

9.2. Add a menu XML resource

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

File

?

New

?

Other…

?

Android

?

Android XML File

.

Select the

Menu

option, enter

mainmenu.xml

as the filename and press the

Finish

button.

Creating a new XML resource for the menu

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 the

Layout

tab of the Android editor. Via the

Add

button you can add new entries.

Press the

Add

button and select the

Item

entry. Enter an entry similar to the following screenshot.

How to maintain the menu entries in an menu xml file

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

Title

attribute 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>

9.3. Create and use ActionBar

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

Option

menu button on your phone. If you select one item, you should see a small info message.

Social App running

10. Exercise: Using the contextual action mode

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.

Contextual ActionBar demonstrated

 

 

Leave a Reply