Creating Menus

翻译自google android手册

 

菜单是程序的一个重要部分,他为用户访问程序的功能提供了相似的界面。

Android中有三种类型的应用程序菜单:

 

Options Menu

一个Activity的主要菜单,当用户按下设备上的MENU键时出现的菜单。在Options Menu中菜单项主要分为两类:
Icon Menu
按下MENU键时屏幕底部出现的菜单项。它支持最多6个菜单项。这仅是支持图标、不支持checkbox或者radio button的菜单项。
 
Expanded Menu           如果Options Menu的菜单项多于6项,那么多出来的部分需要通过点击“More”菜单项才能看到。
Context Menu
当用户在一个View上长按时出现的浮动菜单。
Submenu
用户在Options Menu或者一个context menu上按下时打开的浮动菜单。不能在一个submenu中再嵌套另外一个submenu。

菜单定义

除了在程序中直接实例化Menu对象之外,还可以在一个XML文件中定义一个菜单以及其所有项,然后在代码中像加载一个对象一样加载你的菜单资源。在XML文件中定义菜单是更好的方法,因为将界面定义从程序代码中剥离开来,程序的可扩展性更好。

为了定义一个菜单,你可以在res/menu/目录中创建一个XML文件,并使用如下元素定义菜单。

 

<menu>

这个元素定义一个菜单,它必须是根节点,包含一个或者多个下面提到的元素。你也可以在一个<item>中嵌套包含一个<menu>元素来创建一个子菜单。
<item>
这个元素定义一个MenuItem,也就是一个菜单项。
<group>
<item>元素的可选的,不可见的容器。它允许你对菜单项进行归类,从而同类的菜单项共享属性,譬如active state(激活状态)和可见性等。

下面这个例子,在res/menu/game_menu.xml文件中定义:

 

 

 

 

这个菜单包含了两个菜单项,每一个都包含如下属性:

android:id android:icon android:title

Inflating a Menu Resource(这个inflate不知道如何翻译)

你可以使用MenuInflater.inflate()来inflate你的菜单资源(也就是将XML资源转换成程序代码中可编程的对象)。例如,下面的代码就在onCreateOptionsMenu()回调函数中inflate上面的game_menu.xml文件。

 

这段代码就将xml资源inflate到传递进来的menu对象中。

Creating an Options Menu

 

Options Menu

Figure 1. Screenshot of an Options Menu.

 

 

Options Menu一般包含了基本的应用程序功能以及必须的浏览用的项(例如,打开应用程序设置功能)。用户按下设备上的MENU键时就会弹出Options Menu。Figure 1显示了一个Options Menu。

 

当打开Options Menu时,可见的第一部分就是被称为Icon Menu部分(其他部分是其他菜单项),包含了最多6个菜单项。如果你添加超过6个的菜单项,Android就把这6个菜单项和其后的菜单项包含进Expanded Menu中。用户能够点击“More”菜单项打开Expanded Menu。

当用户第一次打开Options Menu时,Android就会调用Activity中的onCreateOptionsMenu()方法。在你的Activity种覆盖这个方法并populate传递给该方法的Menu对象。可以通过inflate一个你的菜单资源来populate这个Menu对象。也可以使用Menu对象的add方法来动态创建菜单。

当用户点击Options Menu的菜单项时,系统将调用onOptionsItemSelected()方法。系统传递用户选择的MenuItem给这个方法。你可以调用getItemId()方法来获取该菜单项的唯一性的ID(可以在menu resource中通过android:id属性来定义,也就是<item>中的android:id,或者在调用add()方法传递一个整数)。你可以匹配该ID来识别用户选择的菜单项并执行相应的动作。

 

例如:

 

 

在这个例子中,getItemId()查询用户选择的菜单项的ID,然后通过switch语句比较ID。当匹配成功时,返回true,否则,default语句传递菜单项给super class。如果你直接继承自Activity类,那么super class返回false,但这总比直接返回false要好。

 

Tip: 如果你的程序中有多个activity,而且,其中几个拥有同样的Options Menu,那么你可以创建一个Aactivity,这个Activity除了实现onCreateOptionsMenu()和onOptionsItemSelected()之外不做其他事。那么所有的Activity就可以继承该类来创建Options Menu。这样,你就可以只管理一套代码了。如果你需要添加其他菜单项,那么你只需要覆盖onCreateOptionMenu()。调用super.onCreateOptionsMenu(),会创建原有的菜单,然后再调用menu.add()来添加新的菜单项。你也能覆盖super class中单个菜单项的行为。
如果你要添加新的菜单项,那么覆盖onCreateOptionsMenu()。调用super.onCreateOptionsMenu()创建原来的菜单,然后通过menu.add()来添加新的菜单项。你也可以覆盖super class中单独一个菜单项的行为。

 

Changing the menu when it opens

onCreateOptionsMenu()方法只有当Options Menu第一次打开时会被调用。系统会保持和重用你在这个方法中定义的Menu直到你的Activity被销毁。如果你想要在每次打开Options Menu时都改变菜单,那么你必须覆盖onPrepareOptionsMenu()方法。你可以在这个方法中添加、移除、disable或者enable菜单项。

 

Note: You should never change items in the Options Menu based on the View currently in focus. When in touch mode (when the user is not using a trackball or d-pad), Views cannot take focus, so you should never use focus as the basis for modifying items in the Options Menu. If you want to provide menu items that are context-sensitive to a View, use a Context Menu.

Creating a Context Menu

你可以为任何一个View创建context menu,但通常是ListView用的最多。当用户对ListView的一个项进行长按,且这个list被注册提供一个context menu,然后列表项通过改变它的背景色——从橙色到白色——在打开context menu之前,来通知用户context menu是可用的。

 

如果你要定义自己的context menu界面和行为,就要覆盖onCreateContextMenu()和onContextItemSelected()方法。

 

例如,下面的onCreateContextMenu()使用了context_menu资源:

 

view参数传递的是用户长按的那个view,menuInfo提供一些额外信息,可以根据这些信息决定创建什么样的菜单。(这些额外信息是如何设定的呢?)

 

当用户选择context menu的菜单项时,系统调用onContextItemSelected()。下面是一个例子:

 

 

 

In this example, the selected item is an item from a ListView. To perform an action on the selected item, the application needs to know the list ID for the selected item (it's position in the ListView). To get the ID, the application calls getMenuInfo(), which returns a AdapterView.AdapterContextMenuInfo object that includes the list ID for the selected item in the id field. 只有ListView返回的才是AdapterContextMenuInfo吧?

A submenu is a menu that the user can open by selecting an item in another menu. You can add a submenu to any menu (except a submenu). Submenus are useful when your application has a lot of functions that can be organized into topics, like items in a PC application's menu bar (File, Edit, View, etc.).

When creating your menu resource, you can create a submenu by adding a <menu> element as the child of an <item>. For example:

 

 

When the user selects an item from a submenu, the parent menu's respective on-item-selected callback method receives the event. For instance, if the above menu is applied as an Options Menu, then the onOptionsItemSelected() method is called when a submenu item is selected.

You can also use addSubMenu() to dynamically add a SubMenu to an existing Menu. This returns the new SubMenu object, to which you can add submenu items, using add()

Other Menu Features

下面这些特性可应用于大多数的menu items.

Menu groups

一个menu group是一组菜单项的集合,一个menu group中的菜单项可以集中管理,共享属性等。 With a group, you can:

可以在一个menu resource文件中,在一个<group>元素中嵌入<item>元素来创建一个menu group;或者,在一个add()方法中指定一个group ID添加菜单项也可以。下面是在一个menu resource文件中创建menu group的例子。

上面这个例子中,同一个group中的菜单项,跟不在这个group的那个第一项,外观上是一样的,这三个菜单项是同级的。但是,你可以通过group id调用group操作的方法来批处理一个group里的菜单项的特性。

Checkable menu items

 

Figure 2. Screenshot of checkable menu items

 

 

菜单很方便用于打开或者关闭一些选项,这需要对单个选项(菜单项)使用checkbox,或者对于互斥的项使用单选按钮。Figure 2展示了一个使用了radio button的菜单项,是checkable的。

 

Note: Options菜单中的Icon Menu是不能显示checkbox或者radio button的。如果你想要一个Icon Menu是checkable的,那么可能是这样的,当该菜单项是Icon Menu时,他是不能checkable的,但点击之后,他只是一个文本菜单项,那么这时它是checkable的,可以显示一个checkbox或者一个radio button。

 

可以在一个<item>中通过android:checkbale属性来设置一个菜单项的checkable行为,或者在<group>元素中使用android:checkableBehavior属性来指定<group>中所有项的checkable状态。请看下面的例子:

 

 

The android:checkableBehavior attribute accepts either:

single
Only one item from the group can be checked (radio buttons)
all
All items can be checked (checkboxes)
none
No items are checkable

你可以在<item>元素中通过设置android:checked属性来设置一个菜单项的默认checked状态,在代码中可以通过setChecked()方法来改变其状态。

当一个checkable的菜单项被选择的时候,系统将调用相应的回调函数进行处理,例如调用onOptionsItemSelected()方法。你必须在菜单项点击事件的回调函数中设置菜单项的checkbox或者radio button的状态,因为它们不会因为你的点击而自动改变状态。你可以通过isChecked()方法查询菜单项的状态,然后通过setChecked()方法来设置其装填。请看下面例子:

 

 

你必须通过这种方法来改变菜单项的checkable状态,否则他的状态是不会改变的。

 

Note: 你对Checkable菜单项的状态的更改仅适应当前这一次操作,当程序关闭时系统不会自动为你保存设置;如果你想保存这些设置,必须使用Shared Preferences来存储。

Shortcut keys

你可以在<item>元素中设置android:alphabeticShortcut和android:numericShortcut属性来设置菜单项的字母或数字快捷键。也可以使用setAlphabeticShortcut(char)和setNumericShortcut(char)来设置,快捷键是不区分大小写的。

快捷键作为菜单项的一个tip显示,在菜单项名下面 (except for items in the Icon Menu, which are displayed only if the user holds the MENU key).

Note: Shortcut keys for menu items only work on devices with a hardware keyboard. Shortcuts cannot be added to items in a Context Menu.

Intents for menu items

Sometimes you'll want a menu item to launch an Activity using an Intent (whether it's an Actvitity in your application or another application). When you know the Intent you want to use and have a specific menu item that should initiate the Intent, you can execute the Intent with startActivity() during the appropriate on-item-selected callback method (such as the onOptionsItemSelected() callback).

However, if you are not certain that the user's device contains an application that handles the Intent, then adding a menu item that executes the Intent can result in a non-functioning menu item, because the Intent might not resolve to an Activity that accepts it. To solve this, Android lets you dynamically add menu items to your menu when Android finds activities on the device that handle your Intent.

If you're not familiar with creating Intents, read the Intents and Intent Filters.

Dynamically adding Intents

When you don't know if the user's device has an application that handles a specific Intent, you can define the Intent and let Android search the device for activities that accept the Intent. When it finds activies that handle the Intent, it adds a menu item for each one to your menu and attaches the appropriate Intent to open the Activity when the user selects it.

To add menu items based on available activities that accept an Intent:

  1. Define an Intent with the category CATEGORY_ALTERNATIVE and/or CATEGORY_SELECTED_ALTERNATIVE, plus any other requirements.
  2. Call Menu.addIntentOptions(). Android then searches for any applications that can perform the Intent and adds them to your menu.

If there are no applications installed that satisfy the Intent, then no menu items are added.

Note: CATEGORY_SELECTED_ALTERNATIVE is used to handle the currently selected element on the screen. So, it should only be used when creating a Menu in onCreateContextMenu().

For example:

@Override
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, dataUri);
    intent
.addCategory(Intent.CATEGORY_ALTERNATIVE);

   
// Search and populate the menu with acceptable offering applications.
    menu
.addIntentOptions(
         R
.id.intent_group,  // Menu group to which new items will be added
         
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 correlate to specific items (none)

   
return true;
}

For each Activity found that provides an Intent filter matching the Intent defined, a menu item is added, using the value in the Intent filter's android:label as the menu item title and the application icon as the menu item icon. The addIntentOptions() method returns the number of menu items added.

Note: When you call addIntentOptions(), it overrides any and all menu items by the menu group specified in the first argument.

Allowing your Activity to be added to menus

You can also offer the services of your Activity to other applications, so your application can be included in the menu of others (reverse the roles described above).

To be included in other application menus, you need to define an Intent filter as usual, but be sure to include the CATEGORY_ALTERNATIVE and/or CATEGORY_SELECTED_ALTERNATIVE values for the Intent filter category. For example:

<intent-filter label="Resize Image">
    ...
   
<category android:name="android.intent.category.ALTERNATIVE" />
   
<category android:name="android.intent.category.SELECTED_ALTERNATIVE" />
    ...
</intent-filter>

Read more about writing Intent filters in the Intents and Intent Filters document.

For a sample application using this technique, see the Note Pad sample code.

↑ Go to top

← Back to User Interface

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值