菜单特性Menu Features
下面是适用于大多数菜单项的一些其他的特性。
菜单组Menu groups
当往菜单中添加新项时,你可以选择把它包含在一个组中。一个菜单组是一些可以共享某些特征的菜单项的集合,比如它们是否可见,是否可用,或者可否复选(checkable)。
一个组由一个整数定义(或者一个XML里的资源ID)。当我们使用接受一个groupId参数的add()方法,比如add(int, int, int, int)添加项时,它将被添加到组中。
你可以通过setGroupVisible()显示或隐藏菜单组;通过启用或禁用这个组;以及通过setGroupCheckable()设置菜单项是否可以复选。
可复选菜单项Checkable menu items
任何菜单项可以被用来表示选项开关的接口。这可以通过一个checkbox来指示一个单独的选项,或者通过一组单选按钮来表示互斥选项。(查看右边的截屏)。
注意: 在图标菜单中的菜单项不能显示复选框或单选按钮。如果你选择让图标按钮中的菜单项变成可复选,那你必须在开关状态变化时自动通过切换图标和文本来指示这个状态。
要让一个单独的项变成可复选,使用 setCheckable() 方法,如下:
menu.add(0, VIBRATE_SETTING_ID, 0, "Vibrate")
.setCheckable(true);
这将为这个菜单项显示一个复选框(除非这是个图标菜单)。当这个item被选中时,通常onOptionsItemSelected()
会被调用。你应该在这里设置复选框状态。你可以用isChecked()来查询这个菜单项的当前状态和用setChecked()来设置复选状态。就像下面一样:
switch (item.getItemId()) {
case VIBRATE_SETTING_ID:
if (item.isChecked()) item.setChecked(false);
else item.setChecked(true);
return true;
...
}
为了创建一组互斥的单选按钮,只要简单的为每个菜单项分配相同的group ID并调用setGroupCheckable()。在这个例子里,你不需要为每个菜单项调用setCheckable()
方法,因为这个组被整体上设置为可复选。下面是在一个子菜单中创建两个互斥选项的例子:
SubMenu subMenu = menu.addSubMenu("Color");
subMenu.add(COLOR_MENU_GROUP, COLOR_RED_ID, 0, "Red");
subMenu.add(COLOR_MENU_GROUP, COLOR_BLUE_ID, 0, "Blue");
subMenu.setGroupCheckable(COLOR_MENU_GROUP, true, true);
在setGroupCheckable()
方法里,第一个参数是我们想设置为可复选的group ID。第二个参数表示是否设置为可复选。最后一个参数代表这些菜单项是否互斥(如果设置为false,则所有的菜单项将会是复选框而不是单选按钮。当这个组设置为互斥时(单选按钮),每当一个新的项被选中时,所有其它的项的选择会自动被清除。
注意: 可复选菜单项倾向于基于每次会话使用,而不保存到设备中。(例如,地图应用程序中的Map mode 设置并不会被保存-截屏如上)。如果有一些应用程序设置你需要为用户保存它,那你应该使用首选项Preferences来保存数据,而通过一个PreferenceActivity来管理它们。
快捷键Shortcut keys
可以为菜单项添加字母或数字快捷键,setAlphabeticShortcut(char)
方法(设置字母快捷键),setNumericShortcut(int)
方法(设置数字快捷键),或者 setShortcut(char,int)
(同时设置字母和数字)。非大小写敏感,比如:
menu.add(0, MENU_QUIT, 0, "Quit")
.setAlphabeticShortcut('q');
现在,当菜单打开时(或者按住菜单键),按”q”键将选择该菜单项。
这个快捷键将以菜单项的提示信息而显示在菜单项名称的下面(除了图标菜单项)。
注意: 快捷键不能添加进一个上下文菜单项中。
菜单项意图Menu item intents
如果你已经阅读过应用程序基础Application Fundamentals,那么你应该多少知道一点Android意图。它允许程序互相绑定,分享信息,以及合作执行用户任务。就像你的应用程序可以发送一个意图来启动浏览器,邮件客户端或者另外一个活动一样,你可以从菜单中执行这样的动作。有两种途径来做这件事:定义一个意图然后分配给一个单独的菜单项,或者定义一个意图并允许Android查找设备上的活动然后动态的为每个符合意图标准的活动添加一个菜单项。
请阅读意图和意图过滤器章节,以获取更多关于意图创建和应用程序提供服务方面的信息。
为一个单独的菜单项设置一个意图Set an intent for a single menu item
如果你想提供一个具体的菜单项来启动一个新的活动,那么你可以通过setIntent()方法具体地为这个菜单项定义一个意图。
比如,在onCreateOptionsMenu() 方法里,你可以用一个意图定义一个新菜单项如下:
MenuItem menuItem = menu.add(0, PHOTO_PICKER_ID, 0, "Select Photo");
menuItem.setIntent(new Intent(this, PhotoPicker.class));
当这个菜单项被选中时,Android将自动启动这个活动。
注意: 这并不会给你的活动返回一个结果。如果你希望返回一个结果,那么不要使用setIntent()
。相反,和通常情况一样在onOptionsMenuItemSelected()
or onContextMenuItemSelected()
回调中处理并调用startActivityForResult().
动态添加意图Dynamically add intents
如果有潜在的多个活动和你的当前活动或所选择菜单项相关,那么这个应用程序可以动态添加菜单项来执行其他的服务。
在菜单创建过程中,定义一个意图,使用Intent.ALTERNATIVE_CATEGORY和/或 Intent.SELECTED_ALTERNATIVE类别,当前选择(如果有的话)的MIME类型,以及其他需求,和你打开一个新活动时想要满足一个意图过滤器一样。然后调用addIntentOptions() 来让Android查找任何满足那些需求的服务并为你添加它们到菜单中。如果已安装的程序没有满足这个意图的,那么将不会有额外的菜单项被添加。
注意: SELECTED_ALTERNATIVE 是用来处理屏幕当前选中元素的。所以,它应该仅当在onCreateContextMenu()
或 onPrepareOptionsMenu()
里面创建菜单项时使用, 后者每次打开选项菜单时会被调用。
下面是一个说明应用程序如何搜索附加服务来显示在它的菜单中的例子。
public boolean onCreateOptionsMenu(Menu menu){
super.onCreateOptionsMenu(menu);
// Create an Intent that describes the requirements to fulfill, to be included
// in our menu. The offering app must include a category value of Intent.CATEGORY_ALTERNATIVE.
Intent intent = new Intent(null, getIntent().getData());
intent.addCategory(Intent.CATEGORY_ALTERNATIVE);
// Search for, and populate the menu with, acceptable offering applications.
menu.addIntentOptions(
thisClass.INTENT_OPTIONS, // Menu group
0, // Unique item ID (none)
0, // Order for the items (none)
this.getComponentName(), // The current Activity name
null, // Specific items to place first (none)
intent, // Intent created above that describes our requirements
0, // Additional flags to control items (none)
null); // Array of MenuItems that corrolate to specific items (none)
return true;
}
对于每个活动,如果其意图过滤器匹配我们所定义的那个意图,则将会添加一个菜单项,使用这个意图过滤器的android:label值作为菜单项的文本。这个addIntentOptions() 方法也会返回所增加菜单项的数目。
请同时注意,当addIntentOptions()
被调用时,它将重写第一个参数指定的所有菜单组里的菜单项。
如果想把你的活动的服务提供给其他应用程序菜单,那么你只需要和通常情况一样定义一个意图过滤器。只是需要确保在一个意图过滤器的<category>
元素的name属性中包含ALTERNATIVE 和/或 SELECTED_ALTERNATIVE值。比如:
<intent-filter label="Resize Image">
...
<category android:name="android.intent.category.ALTERNATIVE" />
<category android:name="android.intent.category.SELECTED_ALTERNATIVE" />
...
</intent-filter>
在意图和意图过滤器文章中有更多关于创建意图过滤器的描述。
要了解使用该技术的一个例子应用程序,可查看NotePad范例代码。