Android Menus 使用详细说明

来源:互联网 发布:多益网络是什么 编辑:程序博客网 时间:2024/04/27 14:38

原文:http://developer.android.com/guide/topics/ui/menus.html

转载地址:http://wiki.eoeandroid.com/Menus

翻译:Gavin Zhuang

更新:2012.06.08


目录

 [隐藏] 
  • 1 菜单-Menus
    • 1.1 在XML中定义菜单
    • 1.2 创建一个选项菜单
      • 1.2.1 单击事件处理
      • 1.2.2 运行时改变菜单项
    • 1.3 创建上下文菜单
      • 1.3.1 创建浮动的上下文菜单
      • 1.3.2 使用上下文动作模式
    • 1.4 创建弹出菜单
      • 1.4.1 处理单击事件
    • 1.5 创建菜单组
      • 1.5.1 使用可选的菜单项
    • 1.6 基于一个Intent添加菜单选项
      • 1.6.1 允许你的活动添加到其他菜单

菜单-Menus

在许多不同类型的应用中,菜单通常是一种用户界面组件。为了提供给用户熟悉且一致的体验,你需要使用菜单API来展示用户动作和你应用中的其他选项。

从安卓3.0系统(API level 11)开始,安卓设备已经不再需要提供专用的菜单按键。基于这种变化,安卓应用需要远离原来所依赖的传统6选项菜单盘,取而代之的是提供一个动作条来显示普通用户的动作。

虽然设计方案和用户使用菜单选项的方式已经改变,但是从语义上定义的一套动作和选项仍然是基于菜单API的。这份指导书将介绍在所有版本的安卓系统中如何去创建三个基本类型的菜单和动作:


选项菜单和动作条

选项菜单对于一个应用的菜单项来说是首要的。你放置其中的动作一般是可以影响整个应用的,例如“搜索”、“写邮件”和“设置”。

假如你为2.3或者更低版本的安卓系统开发应用,那么用户可以通过点击菜单按钮来显示选项菜单盘。

在安卓3.0或者更高的系统中,选项菜单中的选项作为屏幕上动作项和溢出的选项采用动作条显示。从安卓3.0开始,菜单按键是不被赞成的(一些设备一个也没有),所以你需要改为使用动作条来提供动作和其他选项的入口。

请查看关于创建选项菜单的章节。


上下文菜单和上下操作模式

上下文菜单是一种浮动的菜单,是在当用户在一个元件上执行长按动作时显示的。

当开发平台为安卓3.0或者更高的时候,你需要使用上下文操作模式来使所选的内容产生动作。这种模式显示的动作项会影响到在屏幕顶部条上选定的内容,并允许用户选择多项。

请查看关于创建上下文菜单的章节。


弹出窗口菜单

弹出窗口菜单显示一列被锚记为调用菜单列表的列表项。它很好的提供了一个涉及到具体内容或者提供一个命令的第二部分选项的溢出操作。在弹出菜单中的动作不会直接影响到相应的内容,这就是上下文操作所想要的。

请查看创建弹出菜单的章节


在XML中定义菜单

针对所有的菜单类别,安卓系统都提供了一个标准的XML格式来定义菜单项。你可以在一个XML菜单资源中定义一个菜单和它的所有选项,取代了在activity代码中建立菜单。你可以接着在你的活动中或者代码段中扩展菜单资源(载入它作为一个菜单对象)。

使用菜单资源是一个很好的惯例,主要有几个原因:

  • 它更容易在XML中形象化菜单结构;
  • 它把菜单的内容从你应用的行为代码中脱离出来;
  • 它允许你创建交替的菜单结构以适应不同平台版本,屏幕大小,和其他利用应用资源框架的结构。

定义一个菜单,需要在你项目的res/menu/目录下创建一个XML文件以及使用下面这些元件创建菜单:

<menu>

定义一个菜单作为菜单项的容器。<menu>必须作为文件的根结点,这样才能容纳一个或多个<item><group>元件。

<item>

创建一个在菜单中表示一个单独的选项的菜单项。这个元件可能需要包含<menu>网来创建一个子菜单。

<group>

<item>元件中可选且不可见的容器。它允许你去把菜单项归类,所以它们可以分享特性例如激活状态和可视状态。更多的信息,请查看创建菜单组这一章节。


这里是一个命名为 game_menu.xml 的菜单实例:

  <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android">     <item android:id="@+id/new_game"                 android:icon="@drawable/ic_new_game"                 android:title="@string/new_game"                 android:showAsAction="ifRoom"/>     <item android:id="@+id/help"                 android:icon="@drawable/ic_help"                 android:title="@string/help" /> </menu> 

<item>元件支持多种属性,你可以用来定义一个项的样式和行为。菜单上的选项包含了以下属性:

android:id

菜单项唯一的的ID资源,当用户选中这个选项时允许应用通过这个ID来识别这个菜单项。


android:icon

索引一个图片资源作为该项的图标。


android:title

索引一个字符串作为该项的标题


android:showAsAction

载明该项作为一个行为项什么时候和怎样显示在动作条中。


这些是你需要使用的最重要属性,但是还有更多可用的属性。关于所有支持的属性的信息请查阅菜单资源文档。

你可以通过增加一个<menu>元素作为<item>的子项,给任意菜单的项增加子菜单(除了子菜单本身以外)。当你的应用有大量的功能被组织成主题形式,例如电脑应用程序的菜单栏的选项(文件,编辑,查看等等)时子菜单是非常有用的。

例如:

  <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android">          <item android:id="@+id/file"                      android:title="@string/file" >                  <!-- "file" submenu -->                  <menu>                          <item android:id="@+id/create_new"                                      android:title="@string/create_new" />                          <item android:id="@+id/open"                                      android:title="@string/open" />                  </menu>          </item> </menu> 

在你的应用中使用菜单,你可以使用MenuInflater.inflate()寻找需要的菜单资源文件(将文档资源转换成一个可编程的对象)。在接下来的章节,你将看到怎样为每个菜单类型定位菜单文件。

创建一个选项菜单

选项菜单包含了动作以及其他与当前活动上下文相关的选项,例如"搜索","撰写邮件"以及"设置"等.

在你选项菜单中的选项出现在屏幕中的位置时根据你开发应用的版本而定的:

•如果你开发的应用是基于Android 2.3.x(API级别10)或者更低的,那么当用户点击菜单按钮时你的选项菜单的内容出现在屏幕的底部。例如图像1.当菜单打开时,首先看到的是菜单图标的部分,且最多可容纳六个菜单项。如果你的菜单包含了多于六的菜单项,那么Android放置六个选项且其余的放入到溢出的菜单中,用户可以通过选择“更多”选项来打开。

•如果你开发的应用是基于Android 3.0(API级别11)或者更高的,那么菜单选项中的选项可以添加到动作条中。默认情况下,系统会放置所有选项在动作溢出栏中,用户可以打开在动作条右边的动作溢出图标(或者如果设备菜单按钮可用的话,用户可以点击它)。为了能够快速的访问重要的动作,你可以在相应的<item>元件中添加android:showAsAction="ifRoom"使一些选项出现在动作条上(如图2)。

更多关于动作项和其他动作条行为的信息可以查看Action Bar说明。

注意:即使你的开发没有基于Android 3.0或者更高版本,你也可以创建你自己的动作条布局取得相似的效果。例如你如何支持老版本的Android使用动作条,可以查看 Action Bar Compatibility 的实例。

Actionbar.png

图2 Honeycomb Gallery应用上的动作条,显示了导航标签和相机动作项(加上了动作溢出按钮)

从你的活动(Activity)子类或者片段(Fragment)子类你可以声明选项菜单的选项。加入你的活动和片段都声明了选项菜单的选项,那么它们将被集合在UI界面中。活动的选项先显示,然后才是每个片段按顺序添加到活动中。如果需要,你还可以在你需要移动的每个<item>元素中添加 android:orderInCategory的属性重新按次序添加菜单项。

去指定一个活动的选项菜单,需要覆写 onCreateOptionMenu()这个方法(片段提供它们自己的onCreateOptionMenu()回调方法)。在这种方法下,你可以导入你的菜单资源(定义在XML文件中)到Menu提供的回调方法中。例如:

  @Override public boolean onCreateOptionsMenu(Menu menu) {        MenuInflater inflater = getMenuInflater();        inflater.inflate(R.menu.game_menu, menu);        return true; } 

你也可以使用add()方法添加菜单项以及使用findItem()方法取回选项,使用MenuItem APIs修改它们的属性。

如果你已经开发了基于Android 2.3.x或者更低版本的应用,那么当用户第一次打开菜单时系统可以调用onCreateOptionMenu()去创建选项菜单。

如果你已经开发的应用是基于Android 3.0或者更高版本的,当活动(Activity)启动时系统可以调用onCreateOptionsMenu()在动作条上显示选项。


Menuscreenshot1.png

图像1 安卓2.3系统中浏览器的选项菜单

单击事件处理

当用户从选项菜单中选择一个选项时(包括动作条中的动作选项),系统将会调用你的活动中的onOptionsItemSelected()方法。这种方法是通过MenuItem选择的。你可以通过调用getItemId()来识别选项,那么它会返回一个菜单项中特定的ID(定义在菜单资源中的android:id或者通过add()方法赋予其一个整型数)。你可以对已知的菜单项来匹配这个ID去执行适当的动作。例如:

  @Override public boolean onOptionsItemSelected(MenuItem item) {    // Handle item selection    switch (item.getItemId()) {        case R.id.new_game:            newGame();            return true;        case R.id.help:            showHelp();            return true;        default:            return super.onOptionsItemSelected(item);    } } 

当你成功的处理了一个菜单项,则会返回true值。如果你不能处理一个菜单项,那么你需要调用onOptionsItemSelected()基类来实现(默认实现方法返回false值)

如果你的活动(Activity)包含片段(Fragment),那么系统首先会为活动调用onOptionsItemSelected(),然后才是每个片段(每个片段已经按顺序添加)直到有一个返回true值,或者所有的片段都被调用了。

提示:Android 3.0在XML中的菜单项中为你增加了定义点击行为的能力,使用android:onClick属性即可。属性的值必须使用菜单的活动中定义的方法的名称。当系统调用这个方法的时候,方法必须是公共的且接受单独的MenuItem参数。且它是通过菜单项选择的。更多相关信息和例子,请查看Menu Resource文档。

提示:如果你的应用包含多个活动且其中有一部分提供相同的选项菜单,你可以创建一个活动只实现onCreateOptionsMenu()onOptionsItemSelected()这两个方法。然后每个需要使用这个选项菜单的活动继承这个类。这样的话,你可以管理一部分代码来处理菜单动作且每个子类都集成菜单的动作。如果你想要给子活动增加菜单项,只要在这个活动中覆写onCreateOptionsMenu()这个方法即可。调用super.onCreateOptionsMenu(menu)那么原菜单项就被创建了,然后使用menu.add()添加新的菜单项.当然你也可以为个别的菜单项复写基类的动作。

运行时改变菜单项

在系统调用onCreateOptionsMenu()之后,它保留了你填充菜单中的一个实例且不会再调用onCreateOptionsMenu(),除非菜单出于某种原因失效了。然而,你可以使用onCreateOptionsMenu()去创建一个有效的菜单状态且不能在活动的生命周期内改变。

如果你想要在活动的生命周期内基于事件修改选项菜单,你需要在onPrepareOptionsMenu()方法中实现。只有目前存在菜单对象这个方法才能通过,那么你就可以修改它,例如增加,移除或者使选项失效。(片段也可以提供一个onPrepareOptionsMenu()的回调)。

在Android 2.3.x或者更低的版本中,当用户每次打开选项菜单(通过点击菜单按钮)时系统都会调用onPrepareOptionsMenu()

在Android 3.0或者更高版本中,当菜单项提交在动作条时选项菜单被认为是始终打开的。当一个事件发生且你想要执行一个菜单的更新,那么你必须调用invalidateOptionsMenu()这个方法去反馈系统调用的onPrepareOptionsMenu()方法。

注意:你永远不应该改变基于在选项菜单中目前处于焦点View的的选项。当其处于触点状态(用户没有使用循迹球或者d-pad),视图不能处于焦点状态,所以你永远不能在选项菜单中使用焦点来改变选项。假如你想要为视图(View)提供一个上下文敏感的菜单项,请使用上下文菜单。

创建上下文菜单

一个上下文菜单可以提供影响一个特殊选项或者UI中上下文的框架的动作。你可以为任何界面提供一个上下文菜单,但是它们通常在ListViewGridView或者用户可以在每个选项中直接执行的动作的其他界面分类中使用。

这里有两种方法提供一个上下文动作:

•在浮动的上下文菜单中。当用户在一个声明支持上下文菜单的界面中执行一个长点击(按住并保持),那么这个菜单将作为一个菜单项浮动列表显示(类似对话框)。用户可以每次在一个选项上执行一个上下文动作。

•在上下文动作模式下。这种模式是系统实现的动作模式,在屏幕顶部显示上下文动作条动作条影响所选选项的动作选项的模式。当这种模式被激活,用户可以一次在一个动作中执行多个选项(如果你的应用允许这样)。

注意:上下文动作模式只有在Android 3.0或者更高版本可用且当可用时是首选的显示上下文动作的技术。如果你的应用支持的版本低于3.0,那么你需要在这些设备中使用浮动的上下文菜单。

Menuscreenshot3.png

图 3. 浮动上下文菜单截图(左边)和上下文动作条(右边)。

创建浮动的上下文菜单

为了提供一个浮动的上下文菜单:

1、通过调用resisterForContextMenu()来注册上下文菜单相关的视,并在视图中通过它。

如果你的活动使用了ListView或者GridView且你想要每个选项都提供一个相同的上下文菜单,那么需要通过调用ListView或者GridView中的registerForContextMenu()为一个上下文菜单注册所有的选项。


2、在你的活动(Activity)或者片段(Fragment)实现onCreateContextMenu()的方法。

当注册时接收到一个长点击事件,那么系统将会调用你的onCreateContextMenu方法。这是你定义菜单项的地方,通常通过导入一个菜单资源。例如:

  @Override public void onCreateContextMenu(ContextMenu menu, View v,                                ContextMenuInfo menuInfo) {    super.onCreateContextMenu(menu, v, menuInfo);    MenuInflater inflater = getMenuInflater();    inflater.inflate(R.menu.context_menu, menu); } 

MenuInflater允许你从一个菜单资源导入上下文菜单。这种回调方法的参数包含了用户选择的视图和提供关于被选项额外信息的ContextMenu.ContextMenuInfo对象。假如你的活动有若干个提供不同上下文菜单的视图,你需要使用这些参数来确定被导入的上下文菜单。


3、实现onContextItemSelected()

当用户选择一个菜单项时,系统调用这个方法则你可以执行相应的动作。例如:

  @Override public boolean onContextItemSelected(MenuItem item) {    AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();    switch (item.getItemId()) {        case R.id.edit:            editNote(info.id);            return true;        case R.id.delete:            deleteNote(info.id);            return true;        default:            return super.onContextItemSelected(item);    } } 

getItemId()方法为被选的菜单项查询ID,这些ID是你在XML文件中使用android:id属性分配给每个菜单项的。如在XML中定义一个菜单的章节中所讲的。

当你成功的操作了一个菜单项,将返回true值,如果你不能操作菜单项,你需要通过基类来实现菜单项。如果你的活动包含片段(Fragment),那么活动将首先接收到这个回调。当不能操作时通过调用基类,系统将会在每个片段中使用各自的回调方法过掉这个事件,一次一个(每个片段都已经被按顺序添加了)直到返回true或者false已经返回了(默认活动和android.app.Fragment实现时返回false,当不能操作时你总是需要调用基类)。

使用上下文动作模式

上下文动作模式是系统实现的动作模式,重点是在执行上下文动作的用户交互。当一个用户通过选择一个选项使这个模式启用,那么上下文动作条将会出现在呈现用户可执行的当前被选选项的屏幕的顶部。当这种模式被启用,那么用户可以选择多个选项(如果你允许这样的话),取消多个选项以及继续在活动中导航(你允许的尽可能多的)。当用户通过点击返回按钮取消选择所有选项或者选择动作条坐标的完成动作,则动作模式失效且上下文动作条消失。

注意:上下文动作条没有必要与动作条相关联。它们是独立运行的,即时上下文动作条显示超过动作条的位置。

如果你正在开发基于Android 3.0或者更高版本的应用,通常你需要使用上下文动作模式代替浮动上下文菜单来呈现上下文动作。

为提供上下文的视图,通常你需要调用上下文的动作模式如以下两个事件:

•用户在界面中执行长点击。 •用户选择一个复选框或者视图中类似的UI组件。

如何使你的应用调用上下文动作模式且根据你的设计为每个动作定义行为。基本上有两种设计:

•对于个别的任意视图的上下文动作 •对于在ListView或者GridView的选项组的一些上下文动作(允许用户选择多个选项并执行它们所有的动作)。


接下来的部分是描述各个方案所需的设置。

为个别视图启用上下文动作模式

假如仅仅当用户选择特殊视图时你想要调用上下文动作模式,那么你应该:

1、实现ActionMode.Callback接口。在它的回调方法中,你可以为上下文动作条指定动作,相应在动作选项上点击事件,以及为动作模式操作其他生命周期事件。

2、当你想要显示一个动作条(例如当用户长点击视图)时可以调用startActionMode()方法。

例如:

1、实现ActionMode.Callback接口:

  private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() {     // Called when the action mode is created; startActionMode() was called    @Override    public boolean onCreateActionMode(ActionMode mode, Menu menu) {        // Inflate a menu resource providing context menu items        MenuInflater inflater = mode.getMenuInflater();        inflater.inflate(R.menu.context_menu, menu);        return true;    }     // Called each time the action mode is shown. Always called after onCreateActionMode, but    // may be called multiple times if the mode is invalidated.    @Override    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {        return false; // Return false if nothing is done    }     // Called when the user selects a contextual menu item    @Override    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {        switch (item.getItemId()) {            case R.id.menu_share:                shareCurrentItem();                mode.finish(); // Action picked, so close the CAB                return true;            default:                return false;        }    }     // Called when the user exits the action mode    @Override    public void onDestroyActionMode(ActionMode mode) {        mActionMode = null;    } };  

请注意,这些回调事件几乎和选项菜单回调一模一样的,除了这些还可以通过与事件相关的ActionMode对象。你可以使用ActionMode APIs来使CAB各种变化,例如使用setTitle()setSubtitle()来修改标题和子标题(所有被选中的选项都可用)。

同时也请注意上述的例子在当动作模式被注销时设定了mActionMode变量为空。下一步,你将会看到它是如何初始化以及如何在你可用的活动或片段中保存成员变量。

2、当需要时调用startActionMode()去启用上下文动作模式,例如相应一个视图中的长点击:

  someView.setOnLongClickListener(new View.OnLongClickListener() {    // Called when the user long-clicks on someView    public boolean onLongClick(View view) {        if (mActionMode != null) {            return false;        }         // Start the CAB using the ActionMode.Callback defined above        mActionMode = getActivity().startActionMode(mActionModeCallback);        view.setSelected(true);        return true;    } });  

当你调用startActionMode(),系统返回ActionMode被创建。通过保存这个成员变量,你可以在相应其他事件时改变上下文动作条。在上述例子中,ActionMode是被用于确保ActionMode实例不会被重建,在它已经激活的情况下,且在动作模式开始的时候检查成员是否为空。


在ListView或者GridView中启用一批上下文动作

如果在ListView或者GridView(或者另一个AbsListView的扩展类)中你有一个选项分类,且想要允许用户去执行一批动作,你需要:


•实现AbsListView.MultiChoiceModeListener接口且使用setMultiChoiceModeListener()把它设定给一个视图组。在监听回调的方法的时候,你可以为上下文动作条指定动作,在动作项中相应点击事件,或者操作来自ActionMode.Callback接口的其他回调。 •使用CHOICE_MODE_MULTIPLE_MODAL调用setChoiceMode()

例如:

  ListView listView = getListView(); listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL); listView.setMultiChoiceModeListener(new MultiChoiceModeListener() {     @Override    public void onItemCheckedStateChanged(ActionMode mode, int position,                                          long id, boolean checked) {        // Here you can do something when items are selected/de-selected,        // such as update the title in the CAB    }     @Override    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {        // Respond to clicks on the actions in the CAB        switch (item.getItemId()) {            case R.id.menu_delete:                deleteSelectedItems();                mode.finish(); // Action picked, so close the CAB                return true;            default:                return false;        }    }     @Override    public boolean onCreateActionMode(ActionMode mode, Menu menu) {        // Inflate the menu for the CAB        MenuInflater inflater = mode.getMenuInflater();        inflater.inflate(R.menu.context, menu);        return true;    }     @Override    public void onDestroyActionMode(ActionMode mode) {        // Here you can make any necessary updates to the activity when        // the CAB is removed. By default, selected items are deselected/unchecked.    }     @Override    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {        // Here you can perform updates to the CAB due to        // an invalidate() request        return false;    } });  

就是这样,现在当用户通过长点击选择一个选项时,系统将会调用onCreateActionMode()方法且为指定的动作显示一个上下文动作条。当上下文动作条可见时,用户可以选择附加的选项。

在上下文动作提供共同的动作选项的一些情况下,你可能想要添加一个复选框或者相似的允许用户选择的选项的UI组件,因为它们也许不能通过长点击行为发现。当一个用户选择复选框时,你可以通过使用setItemChecked()为各自的选项列表设定选择状态来调用上下文动作模式。

创建弹出菜单

弹出菜单是一个形式上的菜单标记在View上面。它出现在定位的窗口之下,如果那里有空间的话,或者在其上面。它对以下这些是有用的:

  • 为关联到特殊内容的动作提供一个溢出模式的菜单(例如Gmail的邮件头部,如图4所示)。

注意:这是不同于会影响到所选内容的普通动作的上下文菜单。为了使动作能够影响所选内容,使用上下文动作模式或者浮动上下文菜单。

  • 提供一个命令句的第二部分(例如一个标记为"Add"的按钮,使用不同"Add"选项可产生一个弹出菜单)。
  • 提供一个类似不保留持续选项的Spinner的下拉菜单。

注意:弹出菜单在API 11或者更高的版本可用。

如果你在XML中定义你的菜单,这里介绍了你怎样去显示弹出菜单:

1、使用其结构实例化一个弹出菜单,可以获取当前应用的Context和被标记的菜单的View。

2、使用MenuInflater导入你的菜单资源到菜单对象,通过PopupMenu.getMenu()来返回菜单对象。在API 14 及高于14的,你可以用PopupMenu.inflate()来导入。

3、调用PopupMenu.show().

例如,给一个按钮设定其android:onClick属性来显示弹出菜单:

 <ImageButton    android:layout_width="wrap_content"     android:layout_height="wrap_content"     android:src="@drawable/ic_overflow_holo_dark"    android:contentDescription="@string/descr_overflow_button"    android:onClick="showPopup" /> 

在activity中显示弹出菜单如下:

 public void showPopup(View v) {    PopupMenu popup = new PopupMenu(this, v);    MenuInflater inflater = popup.getMenuInflater();    inflater.inflate(R.menu.actions, popup.getMenu());    popup.show();} 

在API 14 或者更高的,你可以组合两行由PopupMenu.inflate()导入的菜单。

当用户选择一个选项或者触摸菜单以外的区域菜单将消失。你可以使用PopupMenu.OnDismissListener来监听菜单消失事件。

Menuscreenshot4.png

图像 4. 在Gmail应用里的弹出菜单,从右上角浮出。

处理单击事件

当用户选择一个菜单项去执行一个动作时,你必须调用setOnMenuItemclickListener()实现PopupMenu.OnMenuItemClickListener接口且用PopupMenu来注册它。当用户选择一个选项时,系统将在你的界面中调用onMenuItemClick()函数来回调。

例如:

  public void showMenu(View v) {    PopupMenu popup = new PopupMenu(this, v)// This activity implements OnMenuItemClickListener    popup.setOnMenuItemClickListener(this);    popup.inflate(R.menu.actions);    popup.show(); }  @Override public boolean onMenuItemClick(MenuItem item) {    switch (item.getItemId()) {        case R.id.archive:            archive(item);            return true;        case R.id.delete:            delete(item);            return true;        default:            return false;    } } 

创建菜单组

菜单组是一个分享某些特征的菜单项集合,使用菜单组,你可以:

  • 使用setGroupVisible()显示或隐藏所有选项;
  • 使用setGroupEnabled()让所有选项有效或无效;
  • 使用setGroupCheckable()指定是否所有选项可选。


在你的菜单资源或者使用add()方法指定的菜单组ID中,你可以在<group>元件里嵌套<item>元件来创建菜单组。

这里有一个包含菜单组的菜单资源例子:

<?xml version="1.0" encoding="utf-8"?><menu xmlns:android="http://schemas.android.com/apk/res/android">   <item android:id="@+id/menu_save"         android:icon="@drawable/menu_save"         android:title="@string/menu_save" />   <group android:id="@+id/group_delete">       <item android:id="@+id/menu_archive"             android:title="@string/menu_archive" />       <item android:id="@+id/menu_delete"             android:title="@string/menu_delete" />   </group></menu>

这些在组里的选项与第一个选项一样的级别显示——在菜单里的所有三个选项是同级别的。然而,你可以通过查询组的ID地址和使用上面列出的方法来修改组里面两个选项的特征。系统还从未分离过组选项。例如,假如你为每一个选项声明android:showAsAction="ifRoom",那么他们将同时出现在动作条上或者动作溢出上。


使用可选的菜单项

一个菜单可以被当做选项开关的接口,独立选项使用复选框,或者互相排斥的选项。组使用单选按钮。图像5显示的是一个使用可选的单选按钮的子菜单。

注意:在图标菜单里的菜单项(来自选项菜单)不能显示复选框或者单选按钮。假如你选择让图标菜单里的选项可选,那么你需要在每次状态改变时手动的改变图标或者文字来表示选择状态。

你可以在<item>元素使用android:checkable属性来定义一个独立菜单项的可选行为,或者在<group>元素里使用android:checkableBehavior属性来为整个组定义。例如,这个菜单组里的所有选项使用单选按钮且可选:

<?xml version="1.0" encoding="utf-8"?><menu xmlns:android="http://schemas.android.com/apk/res/android">   <group android:checkableBehavior="single">       <item android:id="@+id/red"             android:title="@string/red" />       <item android:id="@+id/blue"             android:title="@string/blue" />   </group></menu>

android:checkableBehavior属性可设定为:

single

在菜单组中只有一个选项能被选中(单选按钮)

all

所有选项都可被选(复选框)

none

没有选项可选

你可以在<item>元素里使用android:checked属性来定义选项的默认选择状态或者在代码中使用setChecked()方法来改变状态。

当一个可选的项被选中,系统将调用选项各自的回调方法(例如onOptionsItemSelected())。在这里你必须设定复选框的状态,因为复选框或者单选按钮无法自动改变它们的状态。你可以使用isChecked()查询选项的当前状态,以及使用setChecked()来设定它选中状态。例如:

@Overridepublic boolean onOptionsItemSelected(MenuItem item) {   switch (item.getItemId()) {       case R.id.vibrate:       case R.id.dont_vibrate:           if (item.isChecked()) item.setChecked(false);           else item.setChecked(true);           return true;       default:           return super.onOptionsItemSelected(item);   }}

假如你不通过这种方式来设定选中状态,那么选项的可视状态(复选框或者单选按钮)在用户选中它时将不会改变。当你设定了状态,activity将维持选项的选中状态以至于当用户较迟打开菜单,选中状态你设定为可见。

注意:可选菜单项是被拟用于每个会话基础上的,且不能在应用销毁后保留。假如你想为用户保存应用设定信息,你需要使用Shared Preferences保存数据。

Menuscreenshot5.png

图像5 子菜单选项可选的截图

基于一个Intent添加菜单选项

一些时候你可能想要使用intent来载入一个活动(无论这个活动是在你的应用中或者在其他应用中)。当你知道你想要使用的intent且有一个可以开启这个Intent的具体菜单项时,你可以在合适的选项被选中回调方法时使用startActivity()来开启这个Intent(例如onOptionsItemSelected()回调)。

然而,假如你不确定用户的设备是否包含有处理这个Intent的应用,却还添加了一个菜单项来调用它,这将导致生成一个无功能的菜单项,因为这个Intent可能无法在这个活动中解决。为了解决这个问题,安卓系统可以允许你在设备发现发现了可以处理你的Intent的活动时动态的添加菜单选项。

基于可接受一个Intent的活动的添加菜单方式:

1、使用CATEGORY_ALTERNATIVE 和/或者 CATEGORY_SELECTED_ALTERNATIVE定义一个intent,可以添加其他任意需求。

2、调用Menu.addIntentOptions()方法。安卓系统可以搜寻到任何能够执行这个Intent的应用,且将它们添加到你的菜单中。

假如系统中没有安装可以满足Intent的应用,那么将没有菜单选项可以被添加。

注意:CATEGORY_SELECTED_ALTERNATIVE是被用来处理当前在屏幕上被选中的元素的。所以,它只能在采用onCreateContextMenu()创建菜单时使用。

例如:

@Overridepublic boolean onCreateOptionsMenu(Menu menu){       super.onCreateOptionsMenu(menu);       //创建一个描述所有需要被执行的需求的Intent,包含在我们的菜单中。   // 提供的应用必须包含Intent.CATEGORY_ALTERNATIVE类的值.       Intent intent = new Intent(null, dataUri);       intent.addCategory(Intent.CATEGORY_ALTERNATIVE);       // 利用可接受的提供应用来搜寻和填充菜单       menu.addIntentOptions(                R.id.intent_group,  // 添加新的新的菜单项的菜单组               0,      // 唯一的选项ID (无)                0,      // 目的选项 (无)                this.getComponentName(),   // 当前活动的名字       null,   // 位于第一位的具体选项(无)                intent, // 一句前面描述的需求定义的Intent               0,      // 控制选项的其他标志 (无)                null);  // 具体项目相关的MenuItems阵列 (无)       return true;}

为了让每个活动都能被找到,那么需要提供一个匹配已定义的Intent的容器、一个被添加进来的菜单项、使用在intent容器中类似菜单项名字的android:label的值,以及类似菜单项图标的应用图标。addIntentOptions()方法将返回被添加进来的选项的数量。

注意:当你调用addIntentOptions(),它将覆盖菜单组指定的所有菜单项。


允许你的活动添加到其他菜单

你可也可以为其他应用提供你的Activity(活动)中的服务,所以你的应用也可以被包含在其他应用的菜单中(反之亦可)。

为了能够被添加到其他应用得菜单中,通常你需要定义一个intent(意图)过滤器,但是必须要包含 CATEGORY_ALTERNATIVE 和/或者CATEGORY_SELECTED_ALTERNATIVE 的intent(意图)过滤器类别的值。例如:

<intent-filter label="@string/resize_image">        ...        <category android:name="android.intent.category.ALTERNATIVE" />        <category android:name="android.intent.category.SELECTED_ALTERNATIVE" />        ...</intent-filter>

在Intents and Intents Filters文档中,你可以阅读到更多关于如何书写intent(意图)过滤器的内容。

对于使用这种技术的示例应用,可以查看 Note Pad 示例代码。


0 0
原创粉丝点击