系统在用户单击menu键后显示的菜单叫选项菜单(OptionMenu)
2.10.1 SubMenu
Menu接口只是一个父接口,它有两个子接口
SubMenu
|
代表一个子菜单
|
ContextMenu
|
代表一个上下文菜单
|
Android不同菜单有如下特征:
- 选项菜单:不支持勾选标记,并且只显示菜单的“浓缩(condensed)”标题
- 子菜单(SubMenu):不支持菜单项图标,不支持嵌套子菜单
- 上下文菜单(ContextMenu):不支持菜单快捷键和图标
Menu接口定义了如下方法添加菜单或菜单项
MenuItem add(int titleRes)
|
添加一个新的菜单项
|
MenuItem add(int groupId, int itemId, int order, CharSequence title)
|
添加一个新的处于groupId组的菜单项
|
MenuItem add(int groupId, int itemId, int order, int titleRes)
|
添加一个新的处于groupId组的菜单项
|
MenuItem add(CharSequence title)
|
添加一个新的菜单项
|
SubMenu addSubMenu(int titleResolved)
|
添加一个新的子菜单
|
SubMenu addSubMenu(int groupId, int itemId, int order, int titleRes)
|
添加一个新的处于groupId组的子菜单
|
SubMenu addSubMenu(CharSequence title)
|
添加一个新的子菜单
|
SubMenu addSubMenu(int groupId, int itemId, int order, CharSequence titleRes)
|
添加一个新的处于groupId组的子菜单
|
SubMenu额外提供如下方法:
SubMenu setHeaderIcon(Drawable icon)
|
设置菜单头的图标
|
SubMenu setHeaderIcon(int iconRes)
|
|
SubMenu setHeaderTitle(int titleRes)
|
|
SubMenu setHeaderTitle(CharSequence title)
|
设置菜单头标题
|
SubMenu setHeaderView(View view)
|
使用View来设置菜单头
|
添加菜单或子菜单的步骤如下:
- 重写Activity的onCreateOptionsMenu(Menu menu)的方法,在该方法里调用Menu对象的方法来添加
- 响应菜单项单击事件,重写Activity 的onOptionsItemSelected(MenuItem mi)
代码示例:
public
class
MainActivity
extends
ActionBarActivity {
final int FONT_10 = 0x111;
final int FONT_12 = 0x112;
final int FONT_14 = 0x113;
final int FONT_16 = 0x114;
final int FONT_18 = 0x115;
final int PLAIN_ITEM = 0x11B;
final int FONT_RED = 0x116;
final int FONT_BLUE = 0x117;
final int FONT_GREEN = 0x118;
private EditText edit ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super .onCreate(savedInstanceState);
setContentView(R.layout. activity_main );
edit = (EditText) findViewById(R.id. txt );
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
SubMenu fontMenu = menu.addSubMenu( "font size" );
fontMenu.setIcon(R.drawable. ic_launcher );
fontMenu.setHeaderTitle( "choose font size" );
fontMenu.add(0, FONT_10 , 0, "size 10 font " );
fontMenu.add(0, FONT_12 , 0, "size 12 font " );
fontMenu.add(0, FONT_14 , 0, "size 14 font " );
fontMenu.add(0, FONT_16 , 0, "size 16 font " );
fontMenu.add(0, FONT_18 , 0, "size 18 font " );
menu.add(0, PLAIN_ITEM , 0, "NORMAL MENU" );
SubMenu colorMenu = menu.addSubMenu( "font color" );
colorMenu.setIcon(R.drawable. ic_launcher );
colorMenu.setHeaderIcon(R.drawable. ic_launcher );
colorMenu.setHeaderTitle( "choose font color" );
colorMenu.add(0, FONT_RED , 0, "RED" );
colorMenu.add(0, FONT_GREEN , 0, "GREEN" );
colorMenu.add(0, FONT_BLUE , 0, "BLUE" );
return super .onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem mi) {
// 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.
switch (mi.getItemId()) {
case FONT_10 :
edit .setTextSize(10 * 2);
break ;
case FONT_12 :
edit .setTextSize(12 * 2);
break ;
case FONT_14 :
edit .setTextSize(14 * 2);
break ;
case FONT_16 :
edit .setTextSize(16 * 2);
break ;
case FONT_18 :
edit .setTextSize(18 * 2);
break ;
case FONT_RED :
edit .setTextColor(Color. RED );
break ;
case FONT_GREEN :
edit .setTextColor(Color. GREEN );
break ;
case FONT_BLUE :
edit .setTextColor(Color. BLUE );
break ;
case PLAIN_ITEM :
Toast toast = Toast.makeText(MainActivity. this , "you click normal menu" , Toast. LENGTH_SHORT );
toast.show();
break ;
default :
break ;
}
return true ;
}
final int FONT_10 = 0x111;
final int FONT_12 = 0x112;
final int FONT_14 = 0x113;
final int FONT_16 = 0x114;
final int FONT_18 = 0x115;
final int PLAIN_ITEM = 0x11B;
final int FONT_RED = 0x116;
final int FONT_BLUE = 0x117;
final int FONT_GREEN = 0x118;
private EditText edit ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super .onCreate(savedInstanceState);
setContentView(R.layout. activity_main );
edit = (EditText) findViewById(R.id. txt );
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
SubMenu fontMenu = menu.addSubMenu( "font size" );
fontMenu.setIcon(R.drawable. ic_launcher );
fontMenu.setHeaderTitle( "choose font size" );
fontMenu.add(0, FONT_10 , 0, "size 10 font " );
fontMenu.add(0, FONT_12 , 0, "size 12 font " );
fontMenu.add(0, FONT_14 , 0, "size 14 font " );
fontMenu.add(0, FONT_16 , 0, "size 16 font " );
fontMenu.add(0, FONT_18 , 0, "size 18 font " );
menu.add(0, PLAIN_ITEM , 0, "NORMAL MENU" );
SubMenu colorMenu = menu.addSubMenu( "font color" );
colorMenu.setIcon(R.drawable. ic_launcher );
colorMenu.setHeaderIcon(R.drawable. ic_launcher );
colorMenu.setHeaderTitle( "choose font color" );
colorMenu.add(0, FONT_RED , 0, "RED" );
colorMenu.add(0, FONT_GREEN , 0, "GREEN" );
colorMenu.add(0, FONT_BLUE , 0, "BLUE" );
return super .onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem mi) {
// 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.
switch (mi.getItemId()) {
case FONT_10 :
edit .setTextSize(10 * 2);
break ;
case FONT_12 :
edit .setTextSize(12 * 2);
break ;
case FONT_14 :
edit .setTextSize(14 * 2);
break ;
case FONT_16 :
edit .setTextSize(16 * 2);
break ;
case FONT_18 :
edit .setTextSize(18 * 2);
break ;
case FONT_RED :
edit .setTextColor(Color. RED );
break ;
case FONT_GREEN :
edit .setTextColor(Color. GREEN );
break ;
case FONT_BLUE :
edit .setTextColor(Color. BLUE );
break ;
case PLAIN_ITEM :
Toast toast = Toast.makeText(MainActivity. this , "you click normal menu" , Toast. LENGTH_SHORT );
toast.show();
break ;
default :
break ;
}
return true ;
}
}
2.10.2 使用监听器来监听菜单事件
除了重写onOptionsItemSelected(MenuItem item)方法来为菜单单击事件编写响应之外,Android同样允许开发者为不同菜单绑定监听器:
setOnMenuItemClickListener(MenuItem.OnMenuItemClickListener menuItemClickListener)
在这种方法下,我们可以采用简单方法来添加菜单项,无须为每个菜单项指定ID
2.10.3 创建复选菜单项和单选菜单项
如果希望所创建菜单项是单选菜单项或多选菜单项,可调用MenuItem的如下方法:
setCheckable(boolean checkable) 设置菜单项是否可勾选
setGroupCheckable(int group, boolean checkable, boolean exclusive)设置Group组里的所有菜单项是否可勾选
除此之外,Android还为MenuItem提供了如下方法来设置快捷键:
- setAlphabeticShortcut(char alphaChar): 设置字母快捷键
- setNumericShortcut(char numericChar):设置数字快捷键
- setShortcut(char numericChar, char alphaChar):同时设置两种快捷键
2.10.4 设置与菜单项关联的Activity
应用程序需要单击某菜单项时启动其他Activity(包括其他Service)。对于这种需求,Android甚至不需要开发者编写任何时间处理代码,只要调用MenuItem的setIntent(Intent intent)方法即可
示例代码:
Java
public
class
MainActivity
extends
ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super .onCreate(savedInstanceState);
// setContentView(R.layout.activity_main);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
SubMenu prog = menu.addSubMenu( "load program" );
prog.setHeaderIcon(R.drawable. ic_launcher );
prog.setHeaderTitle( "choose the program you want to launch" );
MenuItem item = prog.add( "check the book java EE" );
item.setIntent( new Intent( this , OtherActivity. class ));
getMenuInflater().inflate(R.menu. main , menu);
return super .onCreateOptionsMenu(menu);
@Override
protected void onCreate(Bundle savedInstanceState) {
super .onCreate(savedInstanceState);
// setContentView(R.layout.activity_main);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
SubMenu prog = menu.addSubMenu( "load program" );
prog.setHeaderIcon(R.drawable. ic_launcher );
prog.setHeaderTitle( "choose the program you want to launch" );
MenuItem item = prog.add( "check the book java EE" );
item.setIntent( new Intent( this , OtherActivity. class ));
getMenuInflater().inflate(R.menu. main , menu);
return super .onCreateOptionsMenu(menu);
}
}
另外程序还需添加class OtherActivity;activity_other.xml; android_manifest.xml文件中还需添加如下代码
<
activity
android:name = ".OtherActivity"
android:name = ".OtherActivity"
android:label="check the book"></activity>
2.10.5 上下文菜单 (又称长按菜单)
Android用ContextMenu来代表上下文
开发上下文不是重写onCreateOptionsMenu(Menu menu)方法,而是重写onCreateContextMenu(ContextMenu menu, View source, ContextMenu.ContextMenuInfo menuInfo)方法。source代表触发上下文菜单的组件
开发上下文菜单的步骤如下:
- 重写Activity的onCreateContextMenu(ContextMenu menu, View source, ContextMenu.ContextMenuInfo menuInfo)
- 调用Activity的registerForContextMenu(View view)方法为view组件注册上下文菜单
- 若需提供响应,可以重写onContextItemSelected(MenuItem mi)方法,或为指定菜单项绑定事件监听器
ContextMenu提供了如下方法,同样可以为上下文菜单设置图标、标题
- ContextMenu setHeaderIcon(Drawable icon)
- ContextMenu setHeaderIcon(int iconRes)
- ContextMenu setHeaderTitle(int titleRes)
示例代码:
public
class
MainActivity
extends
Activity {
final int MENU1 = 0x111;
final int MENU2 = 0x112;
final int MENU3 = 0x113;
private TextView txt ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super .onCreate(savedInstanceState);
setContentView(R.layout. activity_main );
txt = (TextView) findViewById(R.id. txt );
registerForContextMenu( txt );
}
@Override
public void onCreateContextMenu(ContextMenu menu, View source,
ContextMenu.ContextMenuInfo menuInfo) {
menu.add(0, MENU1 , 0, "red" );
menu.add(0, MENU2 , 0, "green" );
menu.add(0, MENU3 , 0, "blue" );
menu.setGroupCheckable(0, true , true );
menu.setHeaderIcon(R.drawable. ic_launcher );
menu.setHeaderTitle( "choose background color" );
}
@Override
public boolean onContextItemSelected(MenuItem mi) {
switch (mi.getItemId())
{
case MENU1 :
mi.setCheckable( true );
txt .setBackgroundColor(Color. RED );
break ;
case MENU2 :
mi.setCheckable( true );
txt .setBackgroundColor(Color. GREEN );
break ;
case MENU3 :
mi.setCheckable( true );
txt .setBackgroundColor(Color. BLUE );
break ;
default :
break ;
}
return true ;
final int MENU1 = 0x111;
final int MENU2 = 0x112;
final int MENU3 = 0x113;
private TextView txt ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super .onCreate(savedInstanceState);
setContentView(R.layout. activity_main );
txt = (TextView) findViewById(R.id. txt );
registerForContextMenu( txt );
}
@Override
public void onCreateContextMenu(ContextMenu menu, View source,
ContextMenu.ContextMenuInfo menuInfo) {
menu.add(0, MENU1 , 0, "red" );
menu.add(0, MENU2 , 0, "green" );
menu.add(0, MENU3 , 0, "blue" );
menu.setGroupCheckable(0, true , true );
menu.setHeaderIcon(R.drawable. ic_launcher );
menu.setHeaderTitle( "choose background color" );
}
@Override
public boolean onContextItemSelected(MenuItem mi) {
switch (mi.getItemId())
{
case MENU1 :
mi.setCheckable( true );
txt .setBackgroundColor(Color. RED );
break ;
case MENU2 :
mi.setCheckable( true );
txt .setBackgroundColor(Color. GREEN );
break ;
case MENU3 :
mi.setCheckable( true );
txt .setBackgroundColor(Color. BLUE );
break ;
default :
break ;
}
return true ;
}
}
2.20.6 使用XML文件定义菜单
一般推荐使用XML资源文件定义菜单,这种方式可以更好地提供解耦
菜单放置于/res/menu目录下
<menu />可以包含的子元素有:
<item />
| 定义菜单项 |
<group />
|
将多个<item />定义的菜单包装成一个菜单组
|
<group />可指定的常用属性有:
checkableBehavior
|
选择行为。none(不可选)、all、single
|
menuCategory
|
分类,指定菜单优先级container、system、secondary和alternative
|
visible
|
是否可见
|
enable
|
是否可用
|
<item />元素用于定义一份菜单项,<item />元素又可包含<menu />元素,位于<item />元素内部的<menu />就代表了子菜单。
<item />元素可指定如下属性
android:id
|
|
title
|
|
icon
|
|
alphabeticShortcut
|
|
numericShortcut
|
|
checkable
|
|
checked
|
|
visible
|
|
enable
|
|
一旦在程序中定义了菜单资源后,接下来还是重写onCreateOptionsMenu、onCreateContextMenu,在这些方法中调用MenuInflater对象的inflate方法装载指定资源对应的菜单即可
示例的xml文件代码如下:
<
menu
xmlns:android
=
"http://schemas.android.com/apk/res/android"
xmlns:app = "http://schemas.android.com/apk/res-auto"
xmlns:tools = "http://schemas.android.com/tools"
tools:context = "com.example.menurestest.MainActivity" >
< item
android:id = "@+id/action_settings"
android:orderInCategory = "100"
android:title = "font_size"
android:icon = "@drawable/ic_launcher"
app:showAsAction = "never" >
< menu >
< group android:checkableBehavior = "single" >
< item
android:id = "@+id/font_10"
android:title = "Font 10" />
< item
android:id = "@+id/font_12"
android:title = "Font 12" />
< item
android:id = "@+id/font_14"
android:title = "Font 14" />
< item
android:id = "@+id/font_16"
android:title = "Font 16" />
< item
android:id = "@+id/font_18"
android:title = "Font 18" />
</ group >
</ menu >
</ item >
< item
android:id = "@+id/plain_item"
android:title = "plain item" />
< item
android:title = "font color"
android:icon = "@drawable/ic_launcher" >
< menu >
< group >
< item
android:id = "@+id/red_font"
android:title = "red font" />
< item
android:id = "@+id/green_font"
android:title = "green font" />
< item
android:id = "@+id/blue_font"
android:title = "blue font" />
</ group >
</ menu >
</ item >
xmlns:app = "http://schemas.android.com/apk/res-auto"
xmlns:tools = "http://schemas.android.com/tools"
tools:context = "com.example.menurestest.MainActivity" >
< item
android:id = "@+id/action_settings"
android:orderInCategory = "100"
android:title = "font_size"
android:icon = "@drawable/ic_launcher"
app:showAsAction = "never" >
< menu >
< group android:checkableBehavior = "single" >
< item
android:id = "@+id/font_10"
android:title = "Font 10" />
< item
android:id = "@+id/font_12"
android:title = "Font 12" />
< item
android:id = "@+id/font_14"
android:title = "Font 14" />
< item
android:id = "@+id/font_16"
android:title = "Font 16" />
< item
android:id = "@+id/font_18"
android:title = "Font 18" />
</ group >
</ menu >
</ item >
< item
android:id = "@+id/plain_item"
android:title = "plain item" />
< item
android:title = "font color"
android:icon = "@drawable/ic_launcher" >
< menu >
< group >
< item
android:id = "@+id/red_font"
android:title = "red font" />
< item
android:id = "@+id/green_font"
android:title = "green font" />
< item
android:id = "@+id/blue_font"
android:title = "blue font" />
</ group >
</ menu >
</ item >
</
menu
>
2.10.7 使用PopupMenu
- 调用new PopupMenu(Context context, View anchor)创建下拉菜单,anchor代表要激发该弹出菜单的组件
- 调用MenuInflater的inflate()方法将菜单资源填充到PopupMenu中
- 调用PopupMenu的show()方法显示弹出式菜单
示例代码:
Java——————…/src/activity_main.java
public
class
MainActivity
extends
ActionBarActivity {
PopupMenu popup = null ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super .onCreate(savedInstanceState);
setContentView(R.layout. activity_main );
}
public void onPopupButtonClick(View button) {
popup = new PopupMenu( this , button);
getMenuInflater().inflate(R.menu. main , popup .getMenu());
popup .setOnMenuItemClickListener( new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
// TODO Auto-generated method stub
switch (item.getItemId()) {
case R.id. exit :
popup .dismiss();
break ;
default :
Toast.makeText(MainActivity. this , "click" +item.getTitle(), Toast. LENGTH_SHORT ).show();
}
return true ;
}
});
popup .show();
PopupMenu popup = null ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super .onCreate(savedInstanceState);
setContentView(R.layout. activity_main );
}
public void onPopupButtonClick(View button) {
popup = new PopupMenu( this , button);
getMenuInflater().inflate(R.menu. main , popup .getMenu());
popup .setOnMenuItemClickListener( new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
// TODO Auto-generated method stub
switch (item.getItemId()) {
case R.id. exit :
popup .dismiss();
break ;
default :
Toast.makeText(MainActivity. this , "click" +item.getTitle(), Toast. LENGTH_SHORT ).show();
}
return true ;
}
});
popup .show();
}
}
xml————————/res/menu/main.xml
<
menu
xmlns:android
=
"http://schemas.android.com/apk/res/android"
xmlns:app = "http://schemas.android.com/apk/res-auto"
xmlns:tools = "http://schemas.android.com/tools"
tools:context = "com.example.popupmenutest.MainActivity" >
< item
android:id = "@+id/action_settings"
android:orderInCategory = "100"
android:title = "@string/action_settings"
app:showAsAction = "never" />
< item
android:id = "@+id/add"
android:title = "add" >
< menu >
< item
android:id = "@+id/copy"
android:title = "copy" />
< item
android:id = "@+id/cut"
android:title = "cut" />
</ menu >
</ item >
< item
android:id = "@+id/exit"
android:title = "hide menu" />
</ menu >
xmlns:app = "http://schemas.android.com/apk/res-auto"
xmlns:tools = "http://schemas.android.com/tools"
tools:context = "com.example.popupmenutest.MainActivity" >
< item
android:id = "@+id/action_settings"
android:orderInCategory = "100"
android:title = "@string/action_settings"
app:showAsAction = "never" />
< item
android:id = "@+id/add"
android:title = "add" >
< menu >
< item
android:id = "@+id/copy"
android:title = "copy" />
< item
android:id = "@+id/cut"
android:title = "cut" />
</ menu >
</ item >
< item
android:id = "@+id/exit"
android:title = "hide menu" />
</ menu >