Download Android-Chapter07-Menus-OLD

Document related concepts
no text concepts found
Transcript
Lesson 7
Using Menus
Victor Matos
Cleveland State University
Portions of this page are reproduced from work created and shared by Google and used according to terms
described in the Creative Commons 3.0 Attribution License.
Using Menus
Why Menus?
•
Menus are used to allow Android apps to enhance their functionality.
•
When displayed, a menu is shown as an overlapping layer on top of the
current UI. After making a selection, the exposed Menu layer disappear.
•
In principle, a single Menu could add an unlimited number of additional
operations (caution - perhaps not a good practice!).
•
An application could have any number of menus.
CAUTION
Android no longer requires a dedicated Menu button. Developers are
advise to migrate away from the notion of a hardware button, as most
new devices do not have one (see Example3).
7–2
Using Menus
Menu Types
Android supports two types of menus:
Options Menu and Context Menu.
1.
The options menu is triggered by
pressing the device’s hardware or
virtual Menu button. There is only
ONE option menu for each UI.
2.
A context menu is raised by a tapand-hold interaction (long-tap) on
the widget associated to the
menu. You may set one context
menu on any widget.
7–3
Using Menus (Legacy Style)
Figure 1. Using an option menu & physical menu button
First Generation G1
Phone. Most modern
handsets do not include a
hardware MENU button
Options
available in
this context
Press the physical
Menu button
A maximum of six entries per
menu. Excess is displayed as
part of the More option
7–4
Using Menus
Figure 2.
Hardware Menu Button
on the SDK4.3 emulator
Press
Menu
button
List of Options
available in
this context
7–5
Using Menus
Figure 2. Hardware Menu Button on the SDK2.3 emulator
Press
Menu
button
List of Options available in this context
7–6
Using Menus
Figure 3.
Using an option menu
& device’s virtual menu
button
(Image from an HTC One Phone)
Press virtual
Menu button
7–7
Using Menus
Figure 4. Dealing with text messages by using the built-in Messaging
app’s context menu
Messages
Context menu
options
7–8
Menus - Legacy Style
Example 1. Attaching a Simple Option and Context Menu
1. In this example an app will show two EditText boxes. Their content will be
formatted using services offered by various menus.
2. When the user clicks on the Option-Menu button the app presents options to
change point-size, and color of the text held in the EditText boxes.
3. When the user applies a long-tap on the second textbox a menu is shown offering
help in changing the text style (Bold, Italic, Underlined)
4. A long-tap on the first textbox displays the same options listed by the option
menu.
A COMMENT ON ‘LEGACY’ STYLES:
A newer (and perhaps better) way of setting
OPTION MENUS is discussed in next examples,
however; CONTEXT MENUS are still constructed
using the strategy described here in Example1.
Based on an example from: The Busy Coder's Guide to Android Development
by Mark L. Murphy Copyright © 2008-2009 CommonsWare, LLC. ISBN: 978-0-9816780-0-9
7–9
Menus - Legacy Style
Example 1
This Option Menu offers a way of changing
the text size & color of the EditText boxes.
Option
Menu
button
After choosing option:
50 points
Click on Menu
button to see
size options
7 – 10
Menus - Legacy Style
Example 1: Using a Context Menu
Each view has its own Context Menu
exposing choices appropriate to each one.
Long-press a
textbox to
invoke its
Context Menu
7 – 11
Menus - Legacy Style
Example1. Option & Context Menu – Main Layout
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
Menu handling code
skeletons made by the ADT
“Blank Activity” wizard.
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
7 – 12
Menus - Legacy Style
Example1. Option & Context Menu – Main Layout
<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/txtBox1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:text="Hello world" />
<EditText
android:id="@+id/txtBox2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:text="Hola mundo" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Press the MENU key, or \nLong-press text-boxes" />
</LinearLayout>
7 – 13
Menus - Legacy Style
Example1. Option & Context Menu – MainActivity.java
public class MainActivity extends Activity {
EditText txtBox1;
EditText txtBox2;
Integer[] arrayPointSize = {10, 20, 30, 40, 50};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
txtBox1 = (EditText)findViewById(R.id.txtBox1);
txtBox2 = (EditText)findViewById(R.id.txtBox2);
1
// you may register an individual context menu for each view
registerForContextMenu(txtBox1);
registerForContextMenu(txtBox2);
} //onCreate
7 – 14
Menus - Legacy Style
Example1. Option & Context Menu – MainActivity.java
2
// detect what view is calling and create its context menu
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
// decide what context menu needs to be made
if (v.getId() == txtBox1.getId())
// create a menu for txtBox1 box
populateMyFirstMenu(menu);
if (v.getId() == txtBox2.getId()){
// create a menu for txtBox2 box
populateMySecondMenu(menu);
}
} //onCreateContextMenu
3
// set the option menu for the current activity
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// only one Option-Menu per Activity
populateMyFirstMenu(menu);
return true;
}
7 – 15
Menus - Legacy Style
Example1. Option & Context Menu – MainActivity.java
4
private void populateMyFirstMenu(Menu menu){
int groupId = 0;
//arguments: groupId, optionId, order, title
menu.add(groupId, 1, 1, "10 points");
menu.add(groupId, 2, 2, "20 points");
menu.add(groupId, 3, 3, "30 points");
menu.add(groupId, 4, 4, "40 points");
menu.add(groupId, 5, 5, "50 points");
menu.add(groupId, 6, 8, "Red text");
menu.add(groupId, 7, 7, "Green Text");
menu.add(groupId, 8, 6, "Blue text");
} //populateMyFirstMenu
private void populateMySecondMenu(Menu menu){
int groupId = 0;
//arguments: groupId, optionId, order, title
menu.add(groupId, 9, 1, "Bold");
menu.add(groupId, 10, 2, "Italic");
menu.add(groupId, 11, 3, "Normal");
}//populateMySecondMenu
7 – 16
Menus - Legacy Style
Example1. Option & Context Menu – MainActivity.java
5
6
// called whenever an item in your context menu is selected
@Override
public boolean onContextItemSelected(MenuItem item) {
return applyMenuOption( item );
}
// called whenever an item in your options menu is selected
@Override
public boolean onOptionsItemSelected(MenuItem item) {
return applyMenuOption( item );
}
Note:
boolean
event observers of the type onEvent(. . . ) by convention return:
true to indicate the triggered event has been consumed by the method, and
false to signal that the event is still alive and could be consumed by others.
7 – 17
Menus - Legacy Style
Example1. Option & Context Menu – MainActivity.java
7
// apply the action associated to selected item
private boolean applyMenuOption(MenuItem item){
int menuItemId = item.getItemId(); //1, 2, 3, ...11
String strMsg2 = txtBox2.getText().toString();
if (menuItemId <= 5) {
// first five option are for setting text size (10pt, 20pt, ... )
int newPointSize = arrayPointSize[menuItemId - 1];
txtBox1.setTextSize(newPointSize);
txtBox2.setTextSize(newPointSize);
}
else {
// either change color on txtBox1 or style on txtBox2
if (menuItemId == 6)
txtBox1.setTextColor(color.background_dark | Color.RED); // red
else if (menuItemId == 7)
txtBox1.setTextColor(0xff00ff00); // green
else if (menuItemId == 8)
txtBox1.setTextColor(0xff0000ff); // blue
else if (menuItemId == 9)
txtBox2.setText(beautify(strMsg2, "BOLD")); //bold
else if (menuItemId == 10)
txtBox2.setText(beautify(strMsg2, "ITALIC")); //italic
else if (menuItemId == 11)
txtBox2.setText(beautify(strMsg2, "NORMAL")); //normal
}
return false;
} //applyMenuOption
7 – 18
Menus - Legacy Style
Example1. Option & Context Menu – MainActivity.java
// changing text style using HTML formatting
// Spanned is text to which you could add formatting features
8
private Spanned beautify (String originalText, String selectedStyle){
Spanned answer = null;
if (selectedStyle.equals("BOLD"))
answer = Html.fromHtml("<b>" + originalText +"</b>");
else if (selectedStyle.equals("ITALIC"))
answer = Html.fromHtml("<i>" + originalText +"</i>");
else if (selectedStyle.equals("NORMAL"))
answer = Html.fromHtml("<normal>" + originalText +"</normal");
return answer;
} //beautify
} //class
7 – 19
Menus - Legacy Style
Example1. Comments
1. Indicate which widget(s) on your activity have context menus. To do this, call
registerForContextMenu(theWidget)
This statement generates a call to the onCreateContextMenu method.
2. Implement onCreateContextMenu(…), populate your menu adding options.
This method is called each time the context menu is requested, after it is used it
gets discarded
Parameters
menu
The context menu that is being built
v
The view for which the context menu is being built
menuInfo Extra information about the item for which the context menu
should be shown. This information will vary depending on the class of v.
3. Implement onCreateOptionMenu(…). You need to populate the activity’s
menu by adding its options as shown by Bullet 4. An OptionMenu is created only
once for each activity.
7 – 20
Menus - Legacy Style
Example1. Comments
4. The construction of a menu object requires you to supply each individual choice
that will be offered to the user. Choices are added using the statement:
menu.add(groupId, optionId, order, title);
5. To find out which context menu choice was made, you need to implement the
method onContextItemSelected().
6. To service requests for the activity’s OptionMenu you need to override the
method onOptionsItemSelected().
7. After the user clicks on a menu item, a reference to this choice is supplied to our
service routine applyMenuOption. There we use item.getItemId() to
obtain its ID and switch to the appropriate set of service actions.
8. The beautification of simple text is accomplished by applying style HTML tags to
the string. For instance <b><i>simple message</i></b> returns simple message
(Text is rendered bold and in italics)
7 – 21
Menus - Legacy Style
Extending Example1.
Example 2: Enhancing Option/Context Menu with SubMenus
A Menu Hierarchy
This legacy app was
designed for an SDK
predating Level 14 (no
ActionBar on top).
An overlapping layer at
the bottom of the
screen shows up to six
choices for a request
to bring the activity’s
Option Menu.
If you have more than
six selections the
button More will
display the remaining
entries on a simple list.
Keyboard shortcuts / links
Images taken from app targeting SDK 10.
7 – 22
Menus - Legacy Style
Extending Example1.
Example 2: Enhancing Option/Context Menu with SubMenus
A Menu Hierarchy
The previous app is
now shown when
running on an device
set for SDK Level 18.
The overlapping layer
at the bottom of the
screen is replaced by a
floating list of options.
An option in the list
could be a call to
another submenu.
Observe item on fifth
row Sub-Menu-CINCO
is one of such kind.
Images taken from app targeting SDK 18.
7 – 23
Menus - Legacy Style
Extending Example1.
Example 2: Enhancing Option/Context Menu with SubMenus
Creating a
Hierarchy of Menus.
A Sub-Menu item
shows a DialogBox
displaying the
associated
sub-options.
In this example item-5
is a SubMenu type.
Keyboard shortcuts / links
Images taken from app targeting SDK 10.
7 – 24
Menus - Legacy Style
Extending Example1.
Example 2: Enhancing Option/Context Menu with SubMenus
A Sub-Menu item
shows a DialogBox
displaying the
associated suboptions.
Selected sub-menu
item known through its
Keyboard shortcuts / links
.getOrder()
method
Images taken from app targeting SDK 10.
7 – 25
Menus - Legacy Style
Extending Example1.
Example 2: Enhancing
Option/Context Menu
with SubMenus.
Add icons to the app’s folder:
res/drawable
Do this, only in case you are developing a
legacy type app running on a platform
earlier than Level-14.
NOTE
A handful of icons are available in the folder:
… android-sdk/docs/images/icon-design
For standard Android ActionBar icons see:
http://developer.android.com/design/downloads/index.html
7 – 26
Menus - Legacy Style
Example 2: MainActivity.java
Extending Example1.
Replace the method
populateMyFirstMenu
(Example1)
with the following code
private void populateMyFirstMenu(Menu menu){
int groupId = 0;
//arguments: groupId, optionId, order, title
MenuItem item1 = menu.add(groupId, 1, 1, "10 points");
MenuItem item2 = menu.add(groupId, 2, 2, "20 points");
MenuItem item3 = menu.add(groupId, 3, 3, "30 points");
MenuItem item4 = menu.add(groupId, 4, 4, "40 points");
//MenuItem item5 = menu.add(groupId, 5, 5, "50 points");
Remove this line from
previous version
MenuItem item6 = menu.add(groupId, 6, 8, "Red text");
MenuItem item7 = menu.add(groupId, 7, 7, "Green Text");
MenuItem item8 = menu.add(groupId, 8, 6, "Blue text");
//set icons
item1.setIcon(R.drawable.ic_menu_add);
item2.setIcon(R.drawable.ic_menu_add);
item3.setIcon(R.drawable.ic_menu_archive);
item4.setIcon(R.drawable.ic_menu_call);
Icons are added to first four
entries of the Option Menu
7 – 27
Menus - Legacy Style
Example 2: MainActivity.java
Extending Example1.
Replace the method
populateMyFirstMenu
(Example1)
with the following code
// adding a sub-menu as fifth entry of this menu
// .addSubMenu(int groupId, int itemId, int order, CharSequence title)
int smGroupId = 0; // don't care, same as Menu.NONE
int smItemId = 5; // fifth element
int smOrder = 5;
// don't care, same as Menu.NONE
SubMenu mySubMenu5 =
menu.addSubMenu(smGroupId, smItemId, smOrder,
"Sub-Menu-CINCO");
mySubMenu5.setHeaderIcon(R.drawable.btn_rating_star_on_pressed);
mySubMenu5.setIcon(R.drawable.ic_menu_compass);
// .add(int groupId, int itemId, int order, CharSequence title)
MenuItem sub51 = mySubMenu5.add(smGroupId,5,1,"Sub Menu 5-1");
MenuItem sub52 = mySubMenu5.add(smGroupId,5,2,"Sub Menu 5-2");
MenuItem sub53 = mySubMenu5.add(smGroupId,5,3,"Sub Menu 5-3");
} //populateMyFirstMenu
7 – 28
Menus - Legacy Style
Example 2: MainActivity.java
private boolean applyMenuOption(MenuItem item){
Extending Example1.
Replace the method
applyMenuOption
(Example1)
with the following code
int menuItemId = item.getItemId(); //1, 2, 3, ...11
String strMsg2 = txtBox2.getText().toString();
if (menuItemId < 5) {
// first four options are for setting text size
int newPointSize = arrayPointSize[menuItemId - 1];
txtBox1.setTextSize(newPointSize);
txtBox2.setTextSize(newPointSize);
}
else if (menuItemId == 5) {
// the sub-menu (attached to 5th item) is processed here
txtBox1.setText (
"You have selected: \n" +item.getTitle()
+ "\nId: " + menuItemId
+ " order: " + item.getOrder() );
Same as
before
Take care of
sub-menu here
}
// either change color on text1 or style on text2
else if (menuItemId == 6)
txtBox1.setTextColor(0xffff0000); // red
7 – 29
Menus - Legacy Style
Example 2: MainActivity.java
else if (menuItemId == 7)
txtBox1.setTextColor(0xff00ff00); // green
else if (menuItemId == 8)
txtBox1.setTextColor(0xff0000ff); // blue
Extending Example1.
Replace the method
applyMenuOption
(Example1)
with the following code
else if (menuItemId == 9)
txtBox2.setText(beautify(strMsg2, "BOLD")); //bold
else if (menuItemId == 10)
txtBox2.setText(beautify(strMsg2, "ITALIC")); //italic
else if (menuItemId == 11)
txtBox2.setText(beautify(strMsg2, "NORMAL")); //normal
Same as in
Example1
return false;
} //applyMenuOption
7 – 30
Using Menus – Suggested Practice
Example 3: Using the Menu-Snippet Created by Eclipse+ADK
Assume you are using Eclipse and running
and SDK newer than Level 14.
The New > ‘Android Application Project’
wizard allows you to choose a
“Blank Activity”.
The newly created blank activity provides
the skeleton of the onCreate method as
well as two menu handling methods:
onCreateOptionsMenu
onOptionsItemSelected
7 – 31
Using Menus – Suggested Practice
Example 3. Wizard’s Generated Code
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
Menu handling code
skeletons made by the ADT
“Blank Activity” wizard.
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
Using Menus – Suggested Practice
Example 3: Wizard’s – Menu’s XML Definition
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/menu_settings1"
android:orderInCategory="100"
android:title="Menu-Option-1"/>
<item
android:id="@+id/menu_settings2"
android:orderInCategory="110"
android:title="Menu-Option-2"/>
<item
android:id="@+id/menu_settings3"
android:orderInCategory="120"
android:title="Menu-Option-3"/>
</menu>
The call to onCreateOptionsMenu shown in the previous code fragment
inflates the above XML menu file stored in /res/menu/activity_main.xml .
(the file above has been slightly modified to included a few more items)
7 – 33
Using Menus – Suggested Practice
Example 3: Using the Menu-Snippet Created by Eclipse+ADK
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
This code fragment
grabs the selected
item and toasts its ID
and Title. Observe it
returns true to keep
the event alive.
String text = " ID: " + item.getItemId() + " title: " + item.getTitle();
if (id == R.id.menu_settings1) {
Toast.makeText(getApplication(), text, Toast.LENGTH_LONG).show();
return true;
}
if (id == R.id.menu_settings2) {
Toast.makeText(getApplication(), text, Toast.LENGTH_LONG).show();
return true;
}
if (id == R.id.menu_settings3) {
Toast.makeText(getApplication(), text, Toast.LENGTH_LONG).show();
return true;
}
return super.onOptionsItemSelected(item);
}
}
7 – 34
Using Menus – Suggested Practice
Example 3: Using the Menu-Snippet Created by Eclipse+ADK
Our example produces the following snapshots:
ActionBar showing
OVERFLOW button
7 – 35
Using Menus – Suggested Practice
Combining Menus and the ActionBar
The content and location of the ActionBar (discussed in Lesson 6) can be adjusted to
make room not only for its basic Tabs but also portions of the activity’s Option Menu.
There are several reasons to follow this practice:
1. Aesthetics
2. More homogeneous look-&-feel
3. Distribution of the Tabs and menu-items from the OptionMenu is done by the
OS which finds the “best” way of displaying -as much as possible- all of the
requested UI elements (top, bottom, multiple rows, overflow button,
scrollable parts, etc).
4. Allowing the OS to place visual parts of the ActionBar results not only in a
more pleasant rendering of the GUI but also on less code for the developer.
7 – 36
Using Menus – Suggested Practice
Example 4:
Combining Menus and the ActionBar
The app in this example consists of an encapsulating activity and two fragments. The
activity displays an ActionBar that exposes two Tabs: Action1 and Action2.
•
The first Tab (Action1) invokes a ListFragment and the second (Action2) presents a
fragment showing the layout of Example1.
•
As in Example 1, the two textboxes included in Action2 define individual
ContextMenus that when invoked can change the size, color, and style of the text
held in the textviews.
•
The app also adds a global OptionMenu. The choices of the menu include: Search
for a particular text in the list, Reset the list, and an About item.
•
The activity’s OptionMenu is treated as an extension of the ActionBar
7 – 37
Using Menus – Suggested Practice
Example 4:
⟵ Status Bar
Combining Menus
and the ActionBar
⟵ Action Bar
ActionBar and OptionMenu
combined. Image taken from
a phone running SDK 18
(Portrait Mode)
⟵ OptionMenu
7 – 38
Using Menus – Suggested Practice
Example 4:
Combining Menus and the ActionBar
⟵ Status Bar
⟵ Action Bar
showing Tabs and
OptionMenu items
ActionBar and
OptionMenu combined.
Image taken from a
phone running SDK 18
(Landscape Mode)
7 – 39
Using Menus – Suggested Practice
Example 4:
Combining Menus and the ActionBar
Status Bar
ActionBar and
OptionMenu combined.
Image taken from a
Nexus7 tablet running
SDK 18
(Portrait Mode)
Action Bar
showing Tabs and
OptionMenu items
7 – 40
Using Menus – Suggested Practice
Example 4:
Combining Menus and the ActionBar
7 – 41
Using Menus – ActionBar & OptionMenu
Example 4: Layout
activity_main.xml
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/mainLayout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</FrameLayout>
7 – 42
Using Menus – ActionBar & OptionMenu
Example 4: Layout
fragment2_layout.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragment2_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<EditText
android:id="@+id/txtBox1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:text="Hello world" />
<EditText
android:id="@+id/txtBox2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:text="Hola mundo" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Press the MENU key, or \nLong-press text-boxes" />
</LinearLayout>
7 – 43
Using Menus – ActionBar & OptionMenu
Example 4: Layout
search_box.xml
<?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="wrap_content"
android:orientation="horizontal" >
<ImageView
android:id="@+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_action_search" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Search"
android:textAppearance="@android:style/TextAppearance.Medium" />
<EditText
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="2dp"
android:imeActionId="1111"
android:imeOptions="actionDone"
android:inputType="text"
android:width="100sp" />
</LinearLayout>
7 – 44
Using Menus – ActionBar & OptionMenu
Example 4: Menu
option_menu_choices.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/search"
android:actionLayout="@layout/search_box"
android:showAsAction="ifRoom|withText"
android:title="Search"/>
<item
android:id="@+id/reset"
android:icon="@drawable/ic_action_refresh"
android:showAsAction="ifRoom|withText"
android:title="Reset"/>
<item
android:id="@+id/about"
android:icon="@drawable/ic_4_collections_view_as_list"
android:showAsAction="never"
android:title="About"/>
</menu>
7 – 45
Using Menus – ActionBar & OptionMenu
Example 4: Menu
option_menu_choices.xml
<menu
<item
...
android:showAsAction="ifRoom|withText"
.../>
How to show individual
Menu Items
...
</menu>
Value
Description
ifRoom
Put this item in the Action Bar (if there is room for it).
withText
Include the title text (defined by android:title) with the action item.
never
Never place this item in the Action Bar.
always
Always place this item in the Action Bar. It can result in captions
overlapping with other UI in the action bar.
collapseActionView
The action view associated with this action item (as declared by
android:actionLayout or android:actionViewClass) is collapsible..
Reference: http://developer.android.com/guide/topics/resources/menu-resource.html
7 – 46
Using Menus – ActionBar & OptionMenu
Example 4: Main Activity – ActionBarMain.java
public class ActionBarMain extends Activity implements
OnMyCustomRowSelectedListener, TabListener,
OnEditorActionListener {
// TAGs identifying ActionBar TABs
final String TAG1 = "Action1";
final String TAG2 = "Action2";
// this is the row# picked up in Fragment1(ListView)
Integer selectedRow = 0;
String searchWord = "";
String lastTag = TAG1;
// host layout where fragments are displayed
FrameLayout mainLayout;
// fragment objects
FragmentTransaction fragTransactMgr = null;
Fragment currentFragment;
// name
private
private
private
of control variables saved as state info.
final String SELECTED_ROW = "selectedRow";
final String SEARCH_WORD = "searchWord";
final String LAST_TAG = "lastTag";
// reference to SEARCH TextBox
TextView referenceToSearchWord;
7 – 47
Using Menus – ActionBar & OptionMenu
Example 4: Main Activity – ActionBarMain.java
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mainLayout = (FrameLayout) findViewById(R.id.mainLayout);
try {
//
//
//
if
dealing with device rotation & re-starting
if needed bring back previous state info including
selected row and search word, then destroy the bundle
(savedInstanceState != null) {
selectedRow = savedInstanceState.getInt(SELECTED_ROW, 0);
searchWord = savedInstanceState.getString(SEARCH_WORD, "");
lastTag = savedInstanceState.getString(LAST_TAG, TAG1);
savedInstanceState = null;
}
// construct & show the ActionBar for this activity
fragTransactMgr = getFragmentManager().beginTransaction();
ActionBar bar = getActionBar();
// create fresh tab(s) adding caption and icon
bar.addTab(bar.newTab().setText("Action1")
.setTag(TAG1)
.setIcon(R.drawable.ic_4_collections_view_as_list)
.setTabListener(this));
7 – 48
Using Menus – ActionBar & OptionMenu
Example 4: Main Activity – ActionBarMain.java
bar.addTab(bar.newTab().setText("Action2")
.setTag(TAG2)
.setIcon(R.drawable.ic_4_collections_view_as_list)
.setTabListener(this));
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
bar.setDisplayShowHomeEnabled(true);
bar.setDisplayShowTitleEnabled(true);
bar.show();
// clicking on first TAB ("Action1")
bar.selectTab(bar.getTabAt(0));
fragTransactMgr.commit();
} catch (Exception e) {
}
}// onCreate
private void executeFragment(int containerLayoutId, Fragment fragment, String tag) {
// our input fragment comes with a bundle already set with arguments
// replace the indicated layout with the chosen fragment
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(containerLayoutId, fragment, tag);
ft.commit();
}
7 – 49
Using Menus – ActionBar & OptionMenu
Example 4: Main Activity – ActionBarMain.java
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// at the end! (phone was rotated or app was terminated)
// Save important state info (row, tab, searchWord...)
outState.putInt(SELECTED_ROW, selectedRow);
outState.putString(SEARCH_WORD, searchWord);
outState.putString(LAST_TAG, lastTag);
}
// --------------------------------------------------------------------------@Override
public boolean onCreateOptionsMenu(Menu menu) {
// each activity (regardless of how many Fragments it hosts)
// is allowed one OptionMenu. Do the inflation of it here.
getMenuInflater().inflate(R.menu.option_menu_choices, menu);
configureActionItem(menu);
return super.onCreateOptionsMenu(menu);
}
// ---------------------------------------------------------------------------private void configureActionItem(Menu menu) {
// attach a listener to the search-word textbox
EditText searchBox = (EditText) menu.findItem(R.id.search).getActionView()
.findViewById(R.id.title);
searchBox.setOnEditorActionListener(this);
}
7 – 50
Using Menus – ActionBar & OptionMenu
Example 4: Main Activity – ActionBarMain.java
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// OPTIONS-MENU. let user know about the selected menu option
Toast.makeText(this, "Option selected: " + item.getTitle(),
Toast.LENGTH_SHORT).show();
// attending RESET option
if (item.getTitle().equals("Reset")) {
// RESET. make a new Fragment1 passing an int (selectedRow=0)
// this will move the cursor to the top of the list
selectedRow = 0;
searchWord = "";
if ( referenceToSearchWord != null){
referenceToSearchWord.setText(""); // clear search box
}
Fragment fragment = addArgsToFragment(new Fragment1(), selectedRow,
searchWord, lastTag);
executeFragment(R.id.mainLayout, fragment, TAG1);
}
return true;
}
7 – 51
Using Menus – ActionBar & OptionMenu
Example 4: Main Activity – ActionBarMain.java
// Accept a fragment, and simple arguments, put those arguments
// into a bundle and bind the fragment with the bundle.
// This approach is required for apps running SDK Level-14+
public <E extends Fragment> E addArgsToFragment(E fragment, int selectedRow,
String searchWord, String lastTag) {
// E represents: Fragment1, Fragment2, or Fragment3 classes
Bundle bundle = new Bundle();
bundle.putInt(SELECTED_ROW, selectedRow);
bundle.putString(SEARCH_WORD, searchWord);
bundle.putString(LAST_TAG, lastTag);
fragment.setArguments(bundle);
return fragment;
}
//
//
//
//
--------------------------------------------------------------------this method supports fragment-to-Activity communication. When
a row in Fragment1 is selected, our custom callBack is invoked.
It updates the valued of 'selectedRow' held in the main activity.
@Override
public void onMyCustomRowSelected(Integer selectedRow) {
// as soon as the user picks a row in fragment1,
// its value (position in the list) is saved here
this.selectedRow = selectedRow;
}
7 – 52
Using Menus – ActionBar & OptionMenu
Example 4: Main Activity – ActionBarMain.java
@Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
//--------------------------------------------------------------------@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
try {
Fragment fragment = null;
String strTag = (String) tab.getTag();
if (strTag.equals(TAG1)) {
// search fragment
fragment = addArgsToFragment(new Fragment1(), selectedRow,
searchWord, TAG1);
}
if (strTag.equals(TAG2)) {
// reset fragment
fragment = addArgsToFragment(new Fragment2(), selectedRow,
searchWord, TAG2);
}
executeFragment(mainLayout.getId(), fragment, strTag );
} catch (Exception e) {
Toast.makeText(getApplicationContext(),
"MAIN-onTabSelected ERROR:" + tab.getText() + "\n"
+ e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
7 – 53
Using Menus – ActionBar & OptionMenu
Example 4: Main Activity – ActionBarMain.java
@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if ((event == null) || (event.getAction() == KeyEvent.ACTION_UP)) {
// obtain a reference to searchBox, get its text, initiate search
referenceToSearchWord = v;
searchWord = v.getText().toString();
Toast.makeText(getApplicationContext(), "Searching for: " + searchWord,
Toast.LENGTH_SHORT).show();
// remove keyboard from search box
InputMethodManager imm = (InputMethodManager)
getSystemService(INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
// make a new Fragment1 passing a search string, let the new fragment locate
// the searchWord entered in the OptionMenu box.
Fragment fragment = addArgsToFragment(new Fragment1(), selectedRow,
searchWord, lastTag);
executeFragment(R.id.mainLayout, fragment, TAG1);
}
return true;
}
}// class
7 – 54
Using Menus – ActionBar & OptionMenu
Example 4: Fragment1.java – Showing a ListView
7 – 55
Using Menus – ActionBar & OptionMenu
Example 4: Fragment1.java – Showing a ListView
// this fragment shows a ListView from which a row will be selected
public class Fragment1 extends Fragment {
OnMyCustomRowSelectedListener mListener;
int selectedRow = 0;
String searchWord = "";
private String items[] = {
"Text-on-Line-01", "Text-on-Line-02",
"Text-on-Line-04", "Text-on-Line-05",
"Text-on-Line-08", "Text-on-Line-09",
"Text-on-Line-12", "Text-on-Line-13",
"Text-on-Line-03",
"Text-on-Line-06", "Text-on-Line-07",
"Text-on-Line-10", "Text-on-Line-11",
"Text-on-Line-14", "Text-on-Line-15"};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// instead of an XML spec, this view is created with code
Context context = getActivity();
ListView listView = new ListView(context);
7 – 56
Using Menus – ActionBar & OptionMenu
Example 4: Fragment1.java – Showing a ListView
ArrayAdapter<String> adapter = new ArrayAdapter<String>(context,
android.R.layout.simple_list_item_1, items);
listView.setAdapter(adapter);
selectedRow = getArguments().getInt("selectedRow", 0);
searchWord = getArguments().getString("searchWord","");
if (searchWord.length()>0){
selectedRow = findWordInList(searchWord, listView);
}
listView.setSelection(selectedRow);
listView.smoothScrollToPosition(selectedRow);
listView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View v,
int position, long id) {
Toast.makeText(getActivity(), "FRAG1. You picked: " + position, 1)
.show();
// Send the event and clicked item's row ID to the host activity
mListener.onMyCustomRowSelected(position);
}
});
return listView;
}// onCreateView
7 – 57
Using Menus – ActionBar & OptionMenu
Example 4: Fragment1.java – Showing a ListView
private int findWordInList(String searchWord, ListView listView) {
for(int i=0; i<listView.getCount(); i++){
String currentRow = (String) listView.getItemAtPosition(i);
if (currentRow.contains(searchWord)){
Toast.makeText(getActivity(), "FRAG. " + searchWord + " FOUND "+ i, 1).show();
mListener.onMyCustomRowSelected(i);
return i;
}
}
Toast.makeText(getActivity(), "FRAG. " + searchWord + " NOT FOUND", 1).show();
mListener.onMyCustomRowSelected(0);
return 0;
}
//--------------------------------------------------------------------// making sure the MainActivity has implemented the listener
// and can accept our callback messaging
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// Activities containing this fragment must implement its callbacks.
if (!(activity instanceof OnMyCustomRowSelectedListener)) {
throw new IllegalStateException(
"Activity must implement OnMyCustomPictureSelectedListener.");
}
mListener = (OnMyCustomRowSelectedListener) activity;
}// onAttach
}// class
7 – 58
Using Menus – ActionBar & OptionMenu
Example 4: Fragment2.java – Defining a ContextMenu
7 – 59
Using Menus – ActionBar & OptionMenu
Example 4: Fragment2.java – Defining a ContextMenu
7 – 60
Using Menus – ActionBar & OptionMenu
Example 4: Fragment2.java – Defining a ContextMenu
public class Fragment2 extends Fragment {
EditText txtBox1;
EditText txtBox2;
Integer[] arrayPointSize = { 10, 20, 30, 40, 50 };
LinearLayout fragment2Layout;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}// onCreate
// --------------------------------------------------------------------@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment2_layout, null);
fragment2Layout = (LinearLayout) view.findViewById(R.id.fragment2_layout);
txtBox1 = (EditText) view.findViewById(R.id.txtBox1);
txtBox2 = (EditText) view.findViewById(R.id.txtBox2);
// you may register an individual context menu for each view
registerForContextMenu(txtBox1);
registerForContextMenu(txtBox2);
return view;
}// onCreateView
7 – 61
Using Menus – ActionBar & OptionMenu
Example 4: Fragment2.java – Defining a ContextMenu
// detect what view is calling and re-create its context menu
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
// decide what context menu needs to be made
if (v.getId() == txtBox1.getId())
// create a menu for txtBox1 box
makeMyFirstContextMenu(menu);
if (v.getId() == txtBox2.getId()){
// create a menu for txtBox2 box
makeMySecondContextMenu(menu);
}
} //onCreateContextMenu
// --------------------------------------------------------------------private void makeMyFirstContextMenu(Menu menu){
int groupId = 0;
//arguments: groupId, optionId, order, title
menu.add(groupId, 1, 1, "10 points");
menu.add(groupId, 2, 2, "20 points");
menu.add(groupId, 3, 3, "30 points");
menu.add(groupId, 4, 4, "40 points");
menu.add(groupId, 5, 5, "50 points");
menu.add(groupId, 6, 8, "Red text");
menu.add(groupId, 7, 7, "Green Text");
menu.add(groupId, 8, 6, "Blue text");
} //makeMyFirstContextMenu
7 – 62
Using Menus – ActionBar & OptionMenu
Example 4: Fragment2.java – Defining a ContextMenu
private void makeMySecondContextMenu(Menu menu){
int groupId = 0;
//arguments: groupId, optionId, order, title
menu.add(groupId, 9, 1, "Bold");
menu.add(groupId, 10, 2, "Italic");
menu.add(groupId, 11, 3, "Normal");
}//makeMySecondContextMenu
// --------------------------------------------------------------------// called whenever an item in your context menu is selected
@Override
public boolean onContextItemSelected(MenuItem item) {
//return(applyMenuOption(item));
int menuItemId = item.getItemId(); //1, 2, 3, ...11
String strMsg2 = txtBox2.getText().toString();
if (menuItemId <= 5) {
// first five option are for setting text size
int newPointSize = arrayPointSize[menuItemId - 1];
txtBox1.setTextSize(newPointSize);
txtBox2.setTextSize(newPointSize);
}
else {
// either change color on text1 or style on text2
if (menuItemId == 6)
txtBox1.setTextColor(color.background_dark | Color.RED); // red
else if (menuItemId == 7)
txtBox1.setTextColor(0xff00ff00); // green
7 – 63
Using Menus – ActionBar & OptionMenu
Example 4: Fragment2.java – Defining a ContextMenu
else if (menuItemId == 8)
txtBox1.setTextColor(0xff0000ff);
else if (menuItemId == 9)
txtBox2.setText(beautify(strMsg2,
else if (menuItemId == 10)
txtBox2.setText(beautify(strMsg2,
else if (menuItemId == 11)
txtBox2.setText(beautify(strMsg2,
// blue
"BOLD")); //bold
"ITALIC")); //italic
"NORMAL")); //normal
}
return false;
}
// --------------------------------------------------------------------// changing text style using HTML formatting
// Spanned is text to which you could add formatting features
private Spanned beautify (String originalText, String selectedStyle){
Spanned answer = null;
if (selectedStyle.equals("BOLD"))
answer = Html.fromHtml("<b>" + originalText +"</b");
else if (selectedStyle.equals("ITALIC"))
answer = Html.fromHtml("<i>" + originalText +"</i>");
else if (selectedStyle.equals("NORMAL"))
answer = Html.fromHtml("<normal>" + originalText +"</normal");
return answer;
} //beautify
}// class
7 – 64
Using Menus – ActionBar & OptionMenu
Example 4:
OnMyCustomRowSelectedListener.java
Defining a Custom Listener
// Note: The MainActivity must implement this interface !!!
// Used to tell the MainActivity what row from ListView the user
// has selected when interacting with Fragment1 (this is
// functionally equivalent to an onClickLister)
public interface OnMyCustomRowSelectedListener {
public void onMyCustomRowSelected(Integer selectedRow);
}
7 – 65
Using Menus
Questions?
Recommended Additional Reading:
http://developer.android.com/design/style/iconography.html
http://developer.android.com/design/downloads/index.html
http://developer.android.com/guide/topics/ui/themes.html
http://android-developers.blogspot.com/2012/01/say-goodbye-to-menu-button.html