Menu 有几种形式:
1. Context Menu : Context Menu 的菜单项 (Menu Item) 不支持快捷键,也不支持图标。
2. Option Menu 包含两种 Menu : Icon Menu 和 Expanded Menu 。 Icon Menu 的菜单项 (Menu Item) 是唯一支持 Icon 的 Menu Item ,也是唯一不支持 CheckBox 和 Radio 按钮的 Menu Item 。 Expanded Menu 是一个竖直列表,当用户点击 Icon Menu 中的 “more” 菜单项时弹出。 “More” 菜单项,仅在 Icon Menu 菜单项超过 6 个时才会出现。
3. Sub Menu 本身支持 icon ,但 Sub Menu 的菜单项 (Menu Item) 不支持 icon , Sub Menu 也不支持嵌套的 Sub Menu 。
本文仅讨论上面的 2 、 3 两种情况。 Context Menu 将在另外一篇文章中讨论。
1. 首先将本项目要用到的一些图标资源,放入到 res/drawable-mdpi 文件夹下。
它们的文件名分别为:
cn.png 、 uk.png 、 us.png 、 au.png 、 ch.png
它们的文件名分别为:
basketball.png 、 tableball.png 、 usfootball.png 、 volleyball.png 、 boxing.png 、 compass.png 、 football.png 、 golf.png 、 iceskate.png
图片资源放到 res/drawable-mdpi 文件夹后,系统会自动为它们生成对应的 ID 号,比如为 cn.png 生成的 ID 为 R.drawable.cn
2. 创建两个 Activity ,点击某些菜单项时会将界面分别跳转到这两个 Activity 。
第一个 Activity 代码:
public class Countries extends Activity
{
@Override
protected void onCreate(Bundle savedInstanceState)
{
super .onCreate(savedInstanceState);
setContentView(R.layout. countries );
}
}
第一个 Activity 对应的布局文件 countries.xml :
<? xml version = "1.0" encoding = "utf-8" ?>
< LinearLayout
xmlns:android = "http://schemas.android.com/apk/res/android"
android:orientation = "vertical"
android:layout_width = "fill_parent"
android:layout_height = "fill_parent" >
< ImageButton
android:id = "@+id/image_button1"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:src = "@drawable/cn"
/>
< ImageButton
android:id = "@+id/image_button2"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:src = "@drawable/uk"
/>
< ImageButton
android:id = "@+id/image_button3"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:src = "@drawable/us"
/>
< ImageButton
android:id = "@+id/image_button4"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:src = "@drawable/au"
/>
< ImageButton
android:id = "@+id/image_button5"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:src = "@drawable/ch"
/>
</ LinearLayout >
第二个 Activity 代码:
public class Anything extends Activity
{
@Override
protected void onCreate(Bundle savedInstanceState)
{
super .onCreate(savedInstanceState);
setContentView(R.layout. anything );
}
}
第二个 Activity 所对应的布局文件 anything.xml :
<? xml version = "1.0" encoding = "utf-8" ?>
< LinearLayout
xmlns:android = "http://schemas.android.com/apk/res/android"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content" >
< TextView
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:textColor = "#FFFF00"
android:textSize = "30sp"
android:text = "Hello, Android!"
/>
</ LinearLayout >
3. 在 AndroidManifest.xml 中,增加上述两个 Activity 的描述,否则当界面要跳转到它们时,系统会给出找不到 Activity 的警告。在 AndroidManifest.xml 中,在 Application 标签内,增加如下代码:
< activity android:name = ".Countries"
android:label = " 国家 " >
</ activity >
< activity android:name = ".Anything"
android:label = " 随便的信息 " >
</ activity >
4. 所需要的各种代码和素材都已经准备好了,下面主 Activity 的代码 ( 它所对应的布局文件,就用缺省的 main.xml 好了,这个无关紧要 )
public class ControlMenu extends Activity
implements
OnMenuItemClickListener
{
private static final int MAIN_GROUP = 0;
private static final int GENDER_GROUP = 1;
private static final int SPORTS_GROUP = 2;
private static final int GENDER_GROUP_MALE = 3;
private static final int GENDER_GROUP_FEMALE = 4;
private static final int SPORTS_GROUP_BASKETBALL = 5;
private static final int SPORTS_GROUP_ICESKATE = 6;
private static final int SPORTS_GROUP_VOLLEYBALL = 7;
private static final int SPORTS_GROUP_BOXING = 8;
private static final int MENU_GENDER = 9;
@Override
public void onCreate(Bundle savedInstanceState)
{
super .onCreate(savedInstanceState);
setContentView(R.layout. main );
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
super .onCreateOptionsMenu(menu);
// Menu 可以增加 MenuItem , 很显然 , menu_countries 是一个 Icon Menu Item
MenuItem menu_countries = menu.add( " 国籍 " );
// 设定 menu_countries 的图标
menu_countries.setIcon(R.drawable. cn );
// 当 menu_countries 这个菜单项被点击后 , 就会跳转到 Intent 对象中第二个参数所指定的 Activity
menu_countries.setIntent( new Intent( this , Countries. class ));
// =========================================================
// Menu 可以增加 SubMenu 。 SubMenu 可以认为是 Menu 的菜单项
SubMenu subMenuSports = menu.addSubMenu( " 体育 " );
// SubMenu 本身可以有 icon , 但 SubMenu 的菜单项 , 则不支持 icon
subMenuSports.setIcon(R.drawable. tableball );
// 设定 SubMenu 的 HeaderIcon
subMenuSports.setHeaderIcon(R.drawable. usfootball );
// SubMenu 可以增加 MenuItem( 即 SubMenu 的菜单项 )
// public abstract MenuItem add (int groupId, int itemId, int order, CharSequence title)
// add 的第 3 个参数决定菜单项的先后顺序,越小排位越靠前,如果不关心菜单项的排列顺序,
// 可以让这个参数为 Menu.NONE( 即 0)
MenuItem menu_basketball = subMenuSports.add( SPORTS_GROUP , SPORTS_GROUP_BASKETBALL , Menu. NONE , " 篮球 " );
MenuItem menu_volleyball = subMenuSports.add( SPORTS_GROUP , SPORTS_GROUP_VOLLEYBALL , Menu. NONE , " 排球 " );
MenuItem menu_iceskate = subMenuSports.add( SPORTS_GROUP , SPORTS_GROUP_ICESKATE , Menu. NONE , " 滑冰 " );
MenuItem menu_boxing = subMenuSports.add( SPORTS_GROUP , SPORTS_GROUP_BOXING , Menu. NONE , " 拳击 " );
// setGroupCheckable 的第 2 个参数 , 表示整个菜单组里面的菜单项是否可以 checkable
// setGroupCheckable 的第 3 个参数 , 表示菜单项的选择是否为 exclusive
// 如果是 true , 则表明是 exclusive 的 , 即排他的 , 也就是每个菜单项是以单选按钮的形式出现的
// 如果是 false , 则表明是非 exclusive 的 , 即可以多选 , 也就是每个菜单项是以 checkbox 的形式出现的
subMenuSports.setGroupCheckable( SPORTS_GROUP , true , false );
menu_basketball.setChecked( true );
//menu_basketball.setIcon(R.drawable.basketball); // SubMenu 的菜单项 , 即使设置了 Icon , 也不会显示
menu_basketball.setOnMenuItemClickListener( this );
menu_volleyball.setChecked( true );
//menu_volleyball.setIcon(R.drawable.volleyball); // SubMenu 的菜单项 , 即使设置了 Icon , 也不会显示
menu_volleyball.setOnMenuItemClickListener( this );
menu_iceskate.setChecked( false );
//menu_iceskate.setIcon(R.drawable.iceskate); // SubMenu 的菜单项 , 即使设置了 Icon , 也不会显示
menu_iceskate.setOnMenuItemClickListener( this );
menu_boxing.setChecked( false );
//menu_boxing.setIcon(R.drawable.boxing); // SubMenu 的菜单项 , 即使设置了 Icon , 也不会显示
menu_boxing.setOnMenuItemClickListener( this );
// ===========================================================================================
MenuItem menu_anything = menu.add( " 爱好 " );
menu_anything.setIcon(R.drawable. boxing );
menu_anything.setIntent( new Intent( this , Anything. class ));
// 设置快捷键
menu_anything.setAlphabeticShortcut( 'H' );
// ===========================================================================================
SubMenu subMenuGender = menu.addSubMenu( MAIN_GROUP , MENU_GENDER , 0, " 性别 " );
subMenuGender.setIcon(R.drawable. us );
subMenuGender.setHeaderIcon(R.drawable. us );
// add 的第 3 个参数决定菜单项的先后顺序,越小排位越靠前,如果不关心菜单项的排列顺序,
// 可以让这个参数为 Menu.NONE( 即 0) ,下面的代码是会 " 女 " 菜单项在 " 男 " 菜单项之前。
MenuItem male = subMenuGender.add( GENDER_GROUP , GENDER_GROUP_MALE , 2, " 男 " );
male.setChecked( true );
male.setOnMenuItemClickListener( this );
MenuItem female = subMenuGender.add( GENDER_GROUP , GENDER_GROUP_FEMALE , 1, " 女 " );
female.setChecked( false );
female.setOnMenuItemClickListener( this );
// setGroupCheckable 的第 2 个参数 , 表示整个菜单组里面的菜单项是否可以 checkable
// setGroupCheckable 的第 3 个参数 , 表示菜单项的选择是否为 exclusive
// 如果是 true ,则表明是 exclusive 的,即排他的,也就是每个菜单项是以单选按钮的形式出现的
subMenuGender.setGroupCheckable( GENDER_GROUP , true , true );
// ============================================================================================
// 定义一个 Icon Menu Item( 该菜单项不处理任何事件 , 仅为了让 Icon Menu Item 超过 6 个 , 从而出现 “More”)
MenuItem menu_anything3 = menu.add( " 学位 " );
menu_anything3.setIcon(R.drawable. iceskate );
// ============================================================================================
// 定义一个 Icon Menu Item( 该菜单项不处理任何事件 , 仅为了让 Icon Menu Item 超过 6 个 , 从而出现 “More”)
MenuItem menu_anything4 = menu.add( " 语言 " ); // 前面 5 个 Icon MenuItem 加上 More , 因此 Icon MenuItem 会超过 6 个 ,
menu_anything4.setIcon(R.drawable. hk ); // 所以 menu_anything4 , 会变成 Expanded Menu , 也就是说 , 给它设置
// 图标是没有意义的
// ============================================================================================
MenuItem menu_anything5 = menu.add( " 才艺 " ); // 也会变成 Expanded Menu
menu_anything5.setIcon(R.drawable. compass ); // 设置图标是没有意义的
menu_anything5.setIntent( new Intent( this , Anything. class )); // 跳转到 Anything 这个 Activity
return true ;
}
// OnMenuItemClickListener 接口要求我们实现 onMenuItemClick 方法
public boolean onMenuItemClick(MenuItem item)
{
// 功能示例
// 如果 item 是 checked 状态 , 那么点击它以后 , 就会变成 unchecked 状态。反之亦然。
if (item.isChecked())
{
item.setChecked( false );
}
if (!item.isChecked())
{
item.setChecked( true );
}
return true ;
}
// 重写 Activity 中的 onOptionsItemSelected 方法
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
String str = "" ;
// 如果点击的是体育这个菜单项
if (item.getTitle() == " 体育 " )
{
// 检查各菜单项被选中的情况:
if (item.getSubMenu().findItem( SPORTS_GROUP_BASKETBALL ).isChecked()) str += " 篮球 " ;
if (item.getSubMenu().findItem( SPORTS_GROUP_VOLLEYBALL ).isChecked()) str += " 排球 " ;
if (item.getSubMenu().findItem( SPORTS_GROUP_ICESKATE ).isChecked()) str += " 滑冰 " ;
if (item.getSubMenu().findItem( SPORTS_GROUP_BOXING ).isChecked()) str += " 拳击 " ;
// 用 Toast 将 checked 的选项显示出来
Toast.makeText ( this , str, Toast. LENGTH_SHORT ).show();
}
return super .onOptionsItemSelected(item);
}
}
运行结果:
a) 点击模拟器上的 menu 按钮
b) 点击 More :
从上面可以看到,尽管我们给“语言”和“才艺”这两个菜单项,在代码中增加了 Icon ,但在这里是看不到的。也就是说 Expanded Menu Item 是不支持 Icon 的。
c) 在 a) 中点击“国籍”菜单项,将会切换到 Activity Countries 所拥有的界面,如下:
d) 在 a) 中点击“体育”菜单项 ( 其实是一个 SubMenu) ,得到:
因为 subMenuSports.setGroupCheckable(SPORTS_GROUP , true , false ); 中的最后一个参数是 false ,所以显示的菜单项是 Checkbox 形式
e) 在 a) 中点击“爱好”菜单项,将会切换到 Activity Anything 所拥有的界面,如下:
在代码中,我们以 menu_anything.setAlphabeticShortcut('H'); 形式为“爱好”菜单项添加了快捷键,因此,只要点击键盘上的“ h ”键,也会出现上述界面。这个特点在带有键盘的手机上应该比较有用,在没有键盘的手机上 ( 用软键盘 ) ,尽管也可以起作用,但用处不大。
f) 在 a) 中点击“性别”菜单项 ( 其实是个 SubMenu) ,得到:
因为 subMenuGender.setGroupCheckable(GENDER_GROUP , true , true ); 中的最后一个参数是 true ,所以菜单项显示的是 Radio 的形式。
请注意,代码中的 Order 对菜单项显示顺序的影响。
g) “学位”菜单项,我们没有添加相应的代码,因此点击它,不会有什么响应。
h) 点击“ More ”会得到 b) 中所示的 Expanded Menu Item ,点击其中的“语言”菜单项,什么也不会发生,因为我们没有为这个菜单项增加对应的代码。
i) 点击“才艺”,和在 a) 中点击“爱好”菜单项一样,将会切换到 Activity Anything 所拥有的界面。