1 of 61

Menus

HelloMenus Project

2 of 61

HelloMenu

3 of 61

Three types of menus

  • Options menu
    • Icon menu
    • Expanded menu
  • Context menu
  • Submenu

4 of 61

Options menu - Icon Menu

Icon Menu - The menu items visible at the bottom of the screen at the press of the MENU key. It supports a maximum of six menu items. These are the only menu items that support icons and the only menu items that do not support checkboxes or radio buttons.

5 of 61

Options menu - Expanded menu

Expanded Menu - The vertical list of menu items exposed by the "More" menu item in the Icon Menu. When the Icon Menu is full, the expanded menu is comprised of the sixth menu item and the rest.

6 of 61

Context menu

Context Menu - A floating list of menu items that appears when the user performs a long-press on a View.

7 of 61

Submenu

Submenu - A floating list of menu items that the user opens by pressing a menu item in the Options Menu or a context menu. A submenu item cannot support a nested submenu.

8 of 61

HelloMenu

Project, Application, & Activity all just:

HelloMenu

9 of 61

Image resources

Download icons for example:      Hello Menu Icon files

Stolen then edited from the various web locations. Mainly:

http://developer.android.com/guide/practices/ui_guidelines/icon_design.html

10 of 61

Fair warning

Options menu icons should NOT contain color.

http://developer.android.com/guide/practices/ui_guidelines/icon_design_menu.html

But I wanted color for my example. :)

11 of 61

Icon image sizes

12 of 61

Icon filenames

13 of 61

Application icon

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

      package="edu.rosehulman.hellomenu"

      android:versionCode="1"

      android:versionName="1.0">

    <application android:icon="@drawable/ic_hello_menu" android:label="@string/app_name">

        <activity android:name=".HelloMenu"

                  android:label="@string/app_name">

            <intent-filter>

                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />

            </intent-filter>

        </activity>

    </application>

    <uses-sdk android:minSdkVersion="3" />

</manifest> 

14 of 61

Options menu

public boolean onCreateOptionsMenu(Menu menu) 

When the menu button is first pressed, this function is called to create the items in the initial menu.

public boolean onOptionsItemSelected(MenuItem item) 

When an item in the menu is selected this function is the click listener.

public boolean onPrepareOptionsMenu(Menu menu) 

Every time the menu button is pressed this function is called just before the menu is displayed to make changes to account for the current activity state

15 of 61

Declarative vs. Programatic creation

@Override

public boolean onCreateOptionsMenu(Menu menu) {

super.onCreateOptionsMenu(menu);

MenuInflater inflater = getMenuInflater();

inflater.inflate(R.menu.options_menu, menu);

return true;

}

@Override

public boolean onCreateOptionsMenu(Menu menu) {

super.onCreateOptionsMenu(menu);

MenuItem incMenuItem = menu.add(0, ITEM_ID_INCREMENT, Menu.NONE, R.string.increment);

MenuItem decMenuItem = menu.add(0, ITEM_ID_DECREMENT, Menu.NONE, R.string.decrement);

incMenuItem.setIcon(R.drawable.add);

decMenuItem.setIcon(R.drawable.remove);

return true;

}

16 of 61

Google's Advice - Use the XML

  Instead of instantiating Menu objects in your application code, you should define a menu and all its items in an XML menu resource, then inflate the menu resource (load it as a programmable object) in your application code. Defining your menus in XML is a good practice because it separates your interface design from your application code (the same as when you define your Activity layout).

17 of 61

res/menu/options_menu.xml

<?xml version="1.0" encoding="utf-8"?><menu xmlns:android="http://schemas.android.com/apk/res/android>�    <item android:id="@+id/new_game"�          android:icon="@drawable/ic_new_game"�          android:title="@string/new_game" />�    <item android:id="@+id/quit"�          android:icon="@drawable/ic_quit"�          android:title="@string/quit" /></menu>

Google's example

18 of 61

Add this code to HelloMenu

@Override

public boolean onCreateOptionsMenu(Menu menu) {

super.onCreateOptionsMenu(menu);

MenuInflater optionsMenuInflater = getMenuInflater();

optionsMenuInflater.inflate(R.menu.options_menu, menu);

return true;

}

We'll make res/menu/options_menu.xml next

19 of 61

strings.xml

<?xml version="1.0" encoding="utf-8"?>

<resources>

    <string name="hello">Hello World, HelloMenu!</string>

    <string name="app_name">HelloMenu</string>

    <string name="red_background">Red Background</string>

    <string name="yellow_background">Yellow Background</string>

    <string name="blue_background">Blue Background</string>

    <string name="green_background">Green Background</string>

    <string name="white_background">White Background</string>

    <string name="black_background">Black Background</string>

</resources>

20 of 61

options_menu.xml

<?xml version="1.0" encoding="utf-8"?>

<menu

xmlns:android="http://schemas.android.com/apk/res/android">

</menu>

New Android XML menu file

Root element created as a menu

21 of 61

GUI editor

22 of 61

options_menu.xml

<?xml version="1.0" encoding="utf-8"?>

<menu

xmlns:android="http://schemas.android.com/apk/res/android">

<item

android:alphabeticShortcut="y"

android:title="@string/yellow_background"

android:id="@+id/yellow_background"

android:icon="@drawable/ic_menu_yellow_background">

</item>

</menu>

23 of 61

Run and click menu

Neat!

Obviously nothing happens if you click the menu item... yet.

24 of 61

onOptionsItemSelected

public static final String HM = "HM";

@Override

public boolean onOptionsItemSelected(MenuItem item) {

switch( item.getItemId() ) {

case R.id.yellow_background:

Log.d(HM, "Yellow");

// TODO: Actually change the color

return true;

default:

return super.onOptionsItemSelected(item);

}

}

Run it!

Then we'll prepare the main.xml layout

25 of 61

main.xml

FrameLayout and 200dp wide TextView

26 of 61

main.xml

<?xml version="1.0" encoding="utf-8"?>

<FrameLayout

xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:id="@+id/frame_layout">

<TextView

android:layout_height="wrap_content"

android:text="@string/hello"

android:layout_width="200dp"

android:layout_gravity="center"

android:gravity="center"

android:id="@+id/movie_quote_text_view" />

</FrameLayout>

27 of 61

Capture the objects

// Member variables

private FrameLayout mFrameLayout;

private TextView mMovieQuoteTextView;

// Within onCreate

mFrameLayout = (FrameLayout) findViewById(R.id.frame_layout);

mMovieQuoteTextView = (TextView) findViewById(R.id.movie_quote_text_view);

28 of 61

Changing color

@Override

public boolean onOptionsItemSelected(MenuItem item) {

switch( item.getItemId() ) {

case R.id.yellow_background:

Log.d(HM, "Yellow");

this.mFrameLayout.setBackgroundColor(Color.YELLOW);

return true;

default:

return super.onOptionsItemSelected(item);

}

}

Add a few more.  I'll end up with Yellow, White, and Blue, but add whatever you like.

29 of 61

options_menu.xml

<?xml version="1.0" encoding="utf-8"?>

<menu

xmlns:android="http://schemas.android.com/apk/res/android">

<item

android:alphabeticShortcut="y"

android:title="@string/yellow_background"

android:id="@+id/yellow_background"

android:icon="@drawable/ic_menu_yellow_background"></item>

<item

android:alphabeticShortcut="w"

android:title="@string/white_background"

android:id="@+id/white_background"

android:icon="@drawable/ic_menu_white_background"></item>

<item

android:alphabeticShortcut="b"

android:title="@string/blue_background"

android:id="@+id/blue_background"

android:icon="@drawable/ic_menu_blue_background"></item>

</menu>

30 of 61

onClick

@Override

public boolean onOptionsItemSelected(MenuItem item) {

switch( item.getItemId() ) {

case R.id.yellow_background:

this.mFrameLayout.setBackgroundColor(Color.YELLOW);

return true;

case R.id.white_background:

this.mFrameLayout.setBackgroundColor(Color.WHITE);

return true;

case R.id.blue_background:

this.mFrameLayout.setBackgroundColor(Color.BLUE);

return true;

default:

return super.onOptionsItemSelected(item);

}

}

31 of 61

Options menu

Run with 3

Then try it again for more than 6 just to force an expanded menu

32 of 61

Expanded menu

Just repeated the 3 items 3 times YWB YWB YWB

33 of 61

Submenu

Google's sample submenu

Note: It's inside the item

<?xml version="1.0" encoding="utf-8"?>

<menu xmlns:android="http://schemas.android.com/apk/res/android">�    <item android:id="@+id/file" android:icon="@drawable/file"�          android:title="@string/file" >�        <!-- "file" submenu -->�        <menu">�            <item android:id="@+id/new" android:title="@string/new" />�            <item android:id="@+id/open" android:title="@string/open" />�        </menu>�    </item></menu>

34 of 61

Menu groups

<?xml version="1.0" encoding="utf-8"?><menu xmlns:android="http://schemas.android.com/apk/res/android">�    <item android:id="@+id/item1" android:icon="@drawable/item1" android:title="@string/item1" />�    <!-- menu group -->�    <group android:id="@+id/group1">�        <item android:id="@+id/groupItem1" android:title="@string/groupItem1" />�        <item android:id="@+id/groupItem2" android:title="@string/groupItem2" />�    </group></menu>

Google's sample group

Note: A group is not within a item, it "groups" items.

Mainly used for RadioButtons, but can also be used to apply properties to everything in the group (like visibility)

35 of 61

Changing Text Color Item

<string name="text_color">Text Color</string>

<string name="red">Red</string>

<string name="yellow">Yellow</string>

<string name="blue">Blue</string>

<string name="green">Green</string>

<string name="white">White</string>

<string name="black">Black</string>

I'm only gonna use like 4 or so, but here are 6 options

36 of 61

New item with submenu in it

Then in that submenu the items are grouped

37 of 61

options_menu.xml properties

Type

id

title

other

Item

@+id/change_text_color

@string/text_color

@drawable/ic_menu_brush

Sub-menu

--

--

--

Group

--

--

checkable = single

Item

@+id/red_text_color

@string/red

Item

@+id/white_text_color

@string/white

checked = true

Item

@+id/black_text_color

@string/black

Item

@+id/green_text_color

@string/green

38 of 61

Additions to options_menu.xml

<item android:id="@+id/change_text_color"

android:alphabeticShortcut="t"

android:title="@string/text_color"

android:icon="@drawable/ic_menu_brush">

<menu>

<group android:checkableBehavior="single">

<item android:id="@+id/red_text_color"

android:title="@string/red"></item>

<item android:id="@+id/white_text_color"

android:title="@string/white"

android:checked="true"></item>

<item android:id="@+id/black_text_color"

android:title="@string/black"></item>

<item android:id="@+id/green_text_color"

android:title="@string/green"></item>

</group>

</menu>

</item>

39 of 61

Run it.  Submenu & Groups!

40 of 61

Performing an action on a click

//.. Within onOptionsItemSelected

case R.id.black_text_color:

item.setChecked(true);

this.mMovieQuoteTextView.setTextColor(Color.BLACK);

return true;

case R.id.white_text_color:

item.setChecked(true);

this.mMovieQuoteTextView.setTextColor(Color.WHITE);

return true;

case R.id.red_text_color:

item.setChecked(true);

this.mMovieQuoteTextView.setTextColor(Color.RED);

return true;

case R.id.green_text_color:

item.setChecked(true);

this.mMovieQuoteTextView.setTextColor(Color.GREEN);

return true;

41 of 61

Taking action

Make any ugly combo you like

42 of 61

Your turn!

Some text to make an item, submenu, group the submenu items and make that group checkable = all

    <string name="alignment">Alignment</string>

    <string name="top">Top</string>

    <string name="left">Left</string>

Images on next slide

43 of 61

Text alignment submenu

group checkable = all

44 of 61

Adding a checkbox submenu

45 of 61

options_menu.xml

<item android:alphabeticShortcut="a"

android:title="@string/alignment"

android:icon="@drawable/ic_menu_compass">

<menu>

<group android:checkableBehavior="all">

<item android:id="@+id/top"

android:title="@string/top"></item>

<item android:id="@+id/left"

android:title="@string/left"></item>

</group>

</menu>

</item>

46 of 61

Changing the alignment properties

FrameLayout.LayoutParams frameLayoutParams = (FrameLayout.LayoutParams) this.mMovieQuoteTextView.getLayoutParams();

frameLayoutParams.gravity ^= Gravity.LEFT;

this.mMovieQuoteTextView.setLayoutParams(frameLayoutParams);

item.setChecked(!item.isChecked());

47 of 61

Implementing layout params changes

// Above switch

FrameLayout.LayoutParams frameLayoutParams = (FrameLayout.LayoutParams) this.mMovieQuoteTextView.getLayoutParams();

// Within switch

case R.id.left:

item.setChecked(!item.isChecked());

frameLayoutParams.gravity ^= Gravity.LEFT;

this.mMovieQuoteTextView.setLayoutParams(frameLayoutParams);

return true;

case R.id.top:

item.setChecked(!item.isChecked());

frameLayoutParams.gravity ^= Gravity.TOP;

this.mMovieQuoteTextView.setLayoutParams(frameLayoutParams);

return true;

48 of 61

More robust approach (if you care)

if (item.isChecked()) {

frameLayoutParams.gravity |= Gravity.LEFT;

} else {

frameLayoutParams.gravity &= ~Gravity.LEFT;

frameLayoutParams.gravity |= Gravity.CENTER_HORIZONTAL;

}

if (item.isChecked()) {

frameLayoutParams.gravity |= Gravity.TOP;

} else {

frameLayoutParams.gravity &= ~Gravity.TOP;

frameLayoutParams.gravity |= Gravity.CENTER_VERTICAL;

}

// Handy if the checkBox starts off checked.  No changes required for you.

49 of 61

Three types of menus

  • Options menu
    • Icon menu
    • Expanded menu
  • Context menu   < - - - - - - - - - Next!
  • Submenu

50 of 61

A note from Google

Context Menu

  A context menu is conceptually similar to the menu displayed when the user performs a "right-click" on a PC.  You should use a context menu to provide the user access to actions that pertain to a specific item in the user interface. On Android, a context menu is displayed when the user performs a "long press" (press and hold) on an item.

51 of 61

Context menu

public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) 

When a long press is detected on a view that is registered for the context menu, this function is called to create the items in the initial context menu.

public boolean onContextItemSelected(MenuItem item) 

When an item in the context menu is selected this function is the click listener.

52 of 61

Declarative approach again

@Override

public void onCreateContextMenu(ContextMenu menu, View v,

ContextMenuInfo menuInfo) {

super.onCreateContextMenu(menu, v, menuInfo);

MenuInflater contextMenuInflater = getMenuInflater();

contextMenuInflater.inflate(R.menu.context_menu, menu);

}

We'll make res/menu/context_menu.xml next

53 of 61

Add some strings (only a few needed)

<string name="select_quote">Select Quote</string>

<string name="movie_quote_0">Is this heaven? No, it\'s Iowa.</string>

<string name="movie_quote_1">...Bond. James Bond.</string>

<string name="movie_quote_2">Show me the money.</string>

<string name="movie_quote_3">I\'ll be back.</string>

<string name="movie_quote_4">Mama always said, Life was like a box of chocolates.</string>

<string name="movie_quote_5">Get busy livin or get busy dyin."</string>

<string name="movie_quote_6">Gentlemen, you can\'t fight in here! This is the War Room.</string>

<string name="movie_quote_7">It\'s good to be the king!</string>

<string name="movie_quote_8">Hello. My name is Inigo Montoya. You killed my father. Prepare to die.</string>

<string name="movie_quote_9">There\'s no crying in baseball!</string>

54 of 61

res/menu/context_menu.xml

<?xml version="1.0" encoding="utf-8"?>

<menu xmlns:android="http://schemas.android.com/apk/res/android">

<item android:title="@string/movie_quote_0"/>

<item android:title="@string/movie_quote_1" />

<item android:title="@string/movie_quote_2" />

<item android:title="@string/movie_quote_3" />

<item android:title="@string/movie_quote_4" />

<item android:title="@string/movie_quote_5" />

<item android:title="@string/movie_quote_6" />

<item android:title="@string/movie_quote_7" />

<item android:title="@string/movie_quote_8" />

<item android:title="@string/movie_quote_9" />

</menu>

55 of 61

Register for the context menu

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

mFrameLayout= (FrameLayout) findViewById(R.id.frame_layout);

mMovieQuoteTextView = (TextView);

findViewById(R.id.movie_quote_text_view);

registerForContextMenu(this.mMovieQuoteTextView);

}

56 of 61

No declarative solution?

@Override

public void onCreateContextMenu(ContextMenu menu, View v,

ContextMenuInfo menuInfo) {

super.onCreateContextMenu(menu, v, menuInfo);

MenuInflater inflater = getMenuInflater();

inflater.inflate(R.menu.context_menu, menu);

menu.setHeaderTitle(getString(R.string.select_quote));

}

Let me know if someone finds a way to set the header in XML.

57 of 61

Displays the context menu

Selections don't do anything... yet!

58 of 61

onContextItemSelected

@Override

public boolean onContextItemSelected(MenuItem item) {

super.onContextItemSelected(item);

String msg = item.getTitle().toString();

this.mMovieQuoteTextView.setText(msg);

return true;

}

59 of 61

Changing the quote

60 of 61

Finished HelloMenu app

61 of 61

Learning objectives

  • Options menu
    • Icon menu
    • Expanded menu
  • Context menu
  • Submenu