菜单在桌面应用中使用十分广泛,几乎所有的桌面应用都有菜单。菜单在手机应用中的使用减少了不少(主要受到手机屏幕大小制约),但依然有不少手机应用会添加菜单。
与桌面应用的菜单不同,Android应用中的默认菜单是看不见的,只要当用户单击手机上的"Menu"键时,系统才会显示该应用关联的菜单,这种菜单叫选项菜单(OptionMenu)。
注意:从Android3.0开始,Android并不要求手机上必须提供Menu键,可能部分Android手机将不再提供Menu按键。在这样的情况下,Android推荐使用ActionBar来代替菜单。
选项菜单和子菜单(SubMenu)
Android系统的菜单支持主要通过4个接口来实现,下图显示了Android菜单支持的4个接口。
从上图可以看出,Menu接口只是一个父接口,该接口下有如下两个子接口。
- SubMenu:它代表了一个子菜单。可以包含1~N个MenuItem(形成菜单项)。
- ContextMenu:它代表了一个上下文菜单。可以包含1~N个MenuItem(形成菜单项)。
Android的不同菜单具有如下特征。
- 选项菜单(OptionMenu):选项菜单不支持勾选标记,并且只显示菜单的“浓缩(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 titleRes):添加一个新的子菜单。
- SubMenu addSubMenu(int groupId,int itemId,int order,int titleRes):添加一个新的处于groupId组的子菜单。
- SubMenu addSubMenu(CharSequence title):添加一个新的子菜单。
- SubMenu addSubMenu(int groupId,int itemId,int order,CharSequence title):添加一个新的处于groupId组的子菜单。
上面的方法归纳起来就是两个:add()方法用于添加菜单项;addSubMenu()用于添加子菜单。这些重载方法的区别只是:是否将子菜单、菜单项添加到指定菜单组中,是否使用资源文件中的字符串资源来设置标题。
SubMenu继承了Menu,它就代表一个子菜单,额外提供了如下常用方法。
- SubMenu setHeaderIcon(Drawable icon):设置菜单头的图标。
- SubMenu setHeaderIcon(int iconRes):设置菜单头的图标。
- SubMenu setHeaderTitle(int titleRes):设置菜单头的标题。
- SubMenu setHeaderTitle(CharSequence title):设置菜单头的标题。
- SubMenu setHeaderView(View view):使用View来设置菜单头。
掌握了上面Menu、SubMenu、MenuItem的用法之后,接下来就可以通过它们来为Android应用添加菜单或子菜单了。添加菜单或子菜单的步骤如下。
①重写Activity的onCreateOptionsMenu(Menu menu)的方法,在该方法里调用Menu对象的方法来添加菜单项或子菜单。
②如果希望应用程序能响应菜单项的单击事件,重写Activity的onOptionsItemSelected(MenuItem mi)方法即可。
下面的程序示范了如何为Android应用添加菜单或子菜单。
该程序的界面布局文件如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <EditText android:id="@+id/txt" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="用于测试的内容" android:editable="false"/> </LinearLayout>
该Activity的后台代码文件如下:
package org.crazyit.helloworld; import android.os.Bundle; import android.app.Activity; import android.graphics.Color; import android.view.Menu; import android.view.MenuItem; import android.view.SubMenu; import android.widget.EditText; import android.widget.Toast; public class MenuTest extends Activity { //定义字体大小菜单项的标识 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 FLAIN_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.menu_test); edit=(EditText)findViewById(R.id.txt); } @Override public boolean onCreateOptionsMenu(Menu menu) { //-------------向menu中添加字体大小的子菜单-------------- SubMenu fontMenu=menu.addSubMenu("字体大小"); //设置菜单的图标 fontMenu.setIcon(R.drawable.font); //设置菜单头的图标 fontMenu.setHeaderIcon(R.drawable.font); //设置菜单头的标题 fontMenu.setHeaderTitle("选择字体大小"); fontMenu.add(0,FONT_10,0,"10号字体"); fontMenu.add(0,FONT_12,0,"12号字体"); fontMenu.add(0,FONT_14,0,"14号字体"); fontMenu.add(0,FONT_16,0,"16号字体"); fontMenu.add(0,FONT_18,0,"18号字体"); //-------------向menu中添加普通菜单项----------- menu.add(0,FLAIN_ITEM,0,"普通菜单项"); //-------------向menu中添加文字颜色的子菜单----------- SubMenu colorMenu=menu.addSubMenu("字体颜色"); colorMenu.setIcon(R.drawable.color); //设置菜单头的图标 colorMenu.setHeaderIcon(R.drawable.color); //设置菜单头的标题 colorMenu.setHeaderTitle("选择文字颜色"); colorMenu.add(0,FONT_RED,0,"红色"); colorMenu.add(0,FONT_GREEN,0,"绿色"); colorMenu.add(0,FONT_BLUE,0,"蓝色"); // Inflate the menu; this adds items to the action bar if it is present. //getMenuInflater().inflate(R.menu.menu_test, menu); return super.onCreateOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(MenuItem mi) { //判断单击的是哪个菜单项,并有针对性地作出响应 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 FLAIN_ITEM: Toast toast=Toast.makeText(MenuTest.this, "您单击了普通菜单项",Toast.LENGTH_SHORT); toast.show(); break; } // TODO Auto-generated method stub return true; } }
上面的程序中粗体字代码就是添加三个菜单的代码,三个菜单中两个是子菜单,而且程序还为子菜单设置了图标、标题等。
运行上面的程序单击ActionBar程序下方显示的菜单。
用户单击“字体颜色菜单”将看到系统显示下图所示子菜单。
由于程序重写了onOptionsItemSelected(MenuItem mi)方法,因此当用户单击指定菜单项时,程序可以为菜单项的单击事件提供响应,由于程序要在onOptionsItemSelectedSelected(MenuItem item)方法中准确判断到底是哪一个菜单项被单击了,因此添加菜单项时通常应为每个菜单项指定ID。