添加菜单

试用 Compose 方式
Jetpack Compose 是推荐在 Android 设备上使用的界面工具包。了解如何在 Compose 中添加组件。
<ph type="x-smartling-placeholder"></ph> TopAppBar →

菜单是许多应用类型中常见的界面组件。接收者 提供熟悉且一致的用户体验,请使用 Menu API 用于 在您的 Activity 中呈现用户操作和其他选项。

<ph type="x-smartling-placeholder">。 <ph type="x-smartling-placeholder">
</ph> 显示溢出菜单示例的图片
图 1.通过点按图标触发的菜单, 。

本文档介绍了如何创建三种基本类型的菜单或 所有版本的 Android 上的操作演示:

选项菜单和应用栏
选项菜单是菜单项的主集合, 活动。在这里,您可以将对全球影响的 应用(例如“搜索”)“撰写电子邮件”和“设置”

请参阅创建选项菜单 部分。

上下文菜单和关联操作模式
上下文菜单是浮动菜单 在用户触摸屏幕时显示,按住某个元素它 提供了可影响所选内容或上下文框架的操作。

关联操作模式可显示 会影响屏幕顶部栏中的选定内容,并让 用户选择多项内容。

请参阅创建上下文菜单 部分。

弹出式菜单
弹出菜单会显示锚定到 调用该菜单的视图。它适用于提供大量操作 或者为第二部分提供选项 一个命令。弹出式菜单中的操作不会直接影响 对应的内容,这正是关联操作所起到的作用。相反, 弹出菜单适用于与 活动

请参阅创建弹出式菜单部分。

使用 XML 定义菜单

对于所有菜单类型,Android 提供标准的 XML 格式来定义菜单 项。无需在 Activity 的代码中构建菜单,而是定义菜单并 XML 中的所有项。 菜单资源。您可以 然后膨胀菜单资源,即将其作为 Menu 加载 对象 - 在您的 activity 或 fragment 中。

使用菜单资源是一种很好的做法,原因如下:

  • 利用 XML 更易于直观掌握菜单结构。
  • 它会将菜单内容与应用的行为分离开来 代码。
  • 可让您针对不同平台创建备用菜单配置 屏幕尺寸和其他配置 应用资源 框架。

要定义菜单,请在项目的 res/menu/ 目录,然后使用以下代码构建菜单 元素:

<menu>
定义 Menu,即菜单项的容器。答 <menu> 元素必须是该文件的根节点, 可以包含一个或多个 <item><group> 元素。
<item>
创建 MenuItem, 表示菜单中的一项。此元素可以包含嵌套层, <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"
          app: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> 的子元素。 当应用有许多可以整理的函数时,子菜单非常有用 主题,例如 PC 应用菜单栏中的项,例如 File修改查看。请参阅以下示例:

<?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>

如需在 activity 中使用菜单,请 _膨胀_ 菜单资源,然后进行转换 将 XML 资源转换为可编程对象 MenuInflater.inflate()。 以下各部分展示了如何膨胀每种菜单类型的菜单。

创建选项菜单

如图 1 所示的选项菜单,您可以在其中添加 与当前 activity 上下文相关的操作和其他选项; 例如“搜索”“撰写电子邮件”和“设置”

一张图片,显示 Google 表格应用的应用栏
图 2. Google 表格应用,其中显示了 包括操作溢出菜单按钮。

您可以通过 Activity 子类或 Fragment 子类。如果您的 Activity 和片段均针对 选项菜单中,这些项会合并到界面中。系统会显示该活动的项 接着按照 fragment 的排列顺序 就会被添加到 activity 中。如有必要,您可以使用 每个android:orderInCategory 你需要移动 <item>

如需为 activity 指定选项菜单,请替换 onCreateOptionsMenu()。 fragment 提供自己的 onCreateOptionsMenu() 回调。在此方法中,您可以膨胀菜单资源, 在 XML 中定义Menu 回调。具体可见以下示例:

Kotlin

override fun onCreateOptionsMenu(menu: Menu): Boolean {
    val inflater: MenuInflater = menuInflater
    inflater.inflate(R.menu.game_menu, menu)
    return true
}

Java

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

您还可以使用 add() 并使用 findItem() 使用 MenuItem API 修改其属性。

处理点击事件

当用户从选项菜单中选择项目(包括操作项)时 在应用栏中,系统会调用您的 activity 的 onOptionsItemSelected() 方法。此方法会传递所选的 MenuItem。您可以确定 方法是调用 getItemId(), 返回菜单项的唯一 ID,该 ID 由 菜单资源中的 android:id 属性,或指定一个整数 add() 方法。您可以将此 ID 与已知菜单进行匹配 执行适当的操作。

Kotlin

override fun onOptionsItemSelected(item: MenuItem): Boolean {
    // Handle item selection.
    return when (item.itemId) {
        R.id.new_game -> {
            newGame()
            true
        }
        R.id.help -> {
            showHelp()
            true
        }
        else -> super.onOptionsItemSelected(item)
    }
}

Java

@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() 用于 activity,然后用于每个 fragment 按 fragment 的添加顺序进行,直到一个返回 true 或 所有 fragment 都被调用了

<ph type="x-smartling-placeholder">

在运行时更改菜单项

系统调用 onCreateOptionsMenu() 后,会保留一个 您填充但未调用的 Menu 的实例 onCreateOptionsMenu(),除非菜单已失效。 不过,仅使用 onCreateOptionsMenu() 来创建初始菜单 状态,而不是在 activity 生命周期中进行更改。

如果您想根据实验期间发生的事件来修改选项菜单, 可在 activity 生命周期中执行此操作 onPrepareOptionsMenu() 方法。此方法会像目前一样向您传递 Menu 对象 因此您可以对其进行修改,例如添加、删除或停用项目。 Fragment 还提供了 onPrepareOptionsMenu() 回调。

当菜单项显示在以下位置时,选项菜单将被视为始终处于打开状态 打开应用栏发生事件时,如果要执行菜单更新,请调用 invalidateOptionsMenu() 来请求系统调用 onPrepareOptionsMenu()

<ph type="x-smartling-placeholder">

创建上下文菜单

显示悬浮上下文菜单的图片
图 3. 悬浮上下文菜单。

上下文菜单提供了影响特定项目或上下文的操作 帧。您可以为任何视图提供上下文菜单 通常用于 RecylerView 或 其他视图集合,用户可以在这些视图集合中直接对每个视图执行操作 内容。

提供关联操作的方法有两种:

  • 使用悬浮上下文菜单。菜单 会以浮动的菜单项列表的形式显示,类似于对话框, 用户执行触摸和保留声明支持上下文的视图 菜单。用户一次可对一个项目执行上下文操作。
  • 使用关联操作模式。此模式为系统模式 实施 ActionMode 顶部显示了一个关联操作栏 (CAB), 页面,其中包含影响所选项的操作项。当此模式 处于启用状态时,用户可以同时对多项操作执行一项操作 应用支持这一点。

注意上下文菜单不支持内容快捷方式和内容图标。

创建悬浮上下文菜单

如需提供悬浮上下文菜单,请执行以下操作:

  1. 通过以下方式注册与上下文菜单关联的 View: 呼叫 registerForContextMenu() 并向其传递 View

    如果您的 activity 使用 RecyclerView,并且您希望每个 项来提供相同的上下文菜单,请为上下文注册所有项 方法是将 RecyclerView 传递给 registerForContextMenu()

  2. 实施 onCreateContextMenu() 方法 ActivityFragment.

    当注册的视图收到触摸事件时,保留事件,系统会调用 您的 onCreateContextMenu() 方法。在这里,您可以定义 菜单项(通常通过膨胀菜单资源来实现),如下所示 示例:

    Kotlin

        override fun onCreateContextMenu(menu: ContextMenu, v: View,
                                menuInfo: ContextMenu.ContextMenuInfo) {
            super.onCreateContextMenu(menu, v, menuInfo)
            val inflater: MenuInflater = menuInflater
            inflater.inflate(R.menu.context_menu, menu)
        }
        

    Java

        @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 可让您通过菜单资源膨胀上下文菜单。回调方法 参数包括用户选择的 ViewContextMenu.ContextMenuInfo 对象,该对象提供了有关所选项的更多信息。如果 您的 activity 有多个视图,每个视图都提供不同的上下文菜单, 那么您可以使用这些参数来确定要 膨胀。

  3. 实施 onContextItemSelected(), 如以下示例中所示。当用户选择菜单项时, 系统调用此方法,以便您能够执行适当的操作。

    Kotlin

        override fun onContextItemSelected(item: MenuItem): Boolean {
            val info = item.menuInfo as AdapterView.AdapterContextMenuInfo
            return when (item.itemId) {
                R.id.edit -> {
                    editNote(info.id)
                    true
                }
                R.id.delete -> {
                    deleteNote(info.id)
                    true
                }
                else -> super.onContextItemSelected(item)
            }
        }
        

    Java

        @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。如果 不处理菜单项,请将菜单项传递给父类 实施。如果 activity 包含 fragment,则 activity 会收到 此回调。在应用未处理的情况下调用父类, 将事件传递给每个 fragment 中相应的回调方法,其中一个位于 按照每个 fragment 的添加顺序,直到 true 或 返回 false。默认实现 Activityandroid.app.Fragment归来 false,因此请在未处理的情况下始终调用父类。

使用关联操作模式

关联操作模式是 ActionMode,将用户互动重点放在效果上 关联操作。当用户通过选择某项内容来启用此模式时, 关联操作栏 - 显示在屏幕顶部,用于展示内容 以及用户可以对所选商品执行的操作。启用此模式后, 用户可以选择多项内容(如果您的应用支持),还可以取消选择 并继续在 activity 中导航。操作模式已停用 并且当用户取消选择所有项时,上下文操作栏都会消失, 点按“返回”按钮,或点按应用左侧的完成操作 栏。

<ph type="x-smartling-placeholder">

对于提供关联操作的视图,您通常会调用上下文 操作模式:

  • 用户执行触摸和等待视图。
  • 用户选中复选框或视图内类似的界面组件。

您的应用如何调用上下文操作模式以及如何定义 具体取决于您的设计。有两种设计:

  • 针对单个任意视图的关联操作。
  • 针对项目中的项组执行批处理上下文操作 RecyclerView:可让用户选择多项并 执行一项操作

下面几部分介绍了每种场景所需的设置。

为单个视图启用关联操作模式

如果您希望仅在用户选择 执行以下操作:

  1. 实现 ActionMode.Callback 接口,如 示例。在其回调方法中,您可以指定 关联操作栏、响应操作项的点击事件以及 处理操作模式的其他生命周期事件。

    Kotlin

        private val actionModeCallback = object : ActionMode.Callback {
            // Called when the action mode is created. startActionMode() is called.
            override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean {
                // Inflate a menu resource providing context menu items.
                val inflater: MenuInflater = mode.menuInflater
                inflater.inflate(R.menu.context_menu, menu)
                return true
            }
    
            // Called each time the action mode is shown. Always called after
            // onCreateActionMode, and might be called multiple times if the mode
            // is invalidated.
            override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean {
                return false // Return false if nothing is done
            }
    
            // Called when the user selects a contextual menu item.
            override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean {
                return when (item.itemId) {
                    R.id.menu_share -> {
                        shareCurrentItem()
                        mode.finish() // Action picked, so close the CAB.
                        true
                    }
                    else -> false
                }
            }
    
            // Called when the user exits the action mode.
            override fun onDestroyActionMode(mode: ActionMode) {
                actionMode = null
            }
        }
        

    Java

        private ActionMode.Callback actionModeCallback = new ActionMode.Callback() {
    
            // Called when the action mode is created. startActionMode() is 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, and might 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) {
                actionMode = null;
            }
        };
        

    这些事件回调与 选项菜单,只不过其中每个选项 还会传递与事件相关联的 ActionMode 对象。 您可以使用 ActionMode API 对 CAB,如使用 setTitle()setSubtitle(), 这对于指示被选中的项数非常有用

    上面的示例将 actionMode 变量设置为 在操作模式被销毁时返回 null。在下一步中,请参阅 它的初始化方式,以及如何在 activity 中保存成员变量,或 fragment 非常有用。

  2. 致电 startActionMode() 在您希望显示该栏时,例如当用户触摸和 等待视图。

    Kotlin

        someView.setOnLongClickListener { view ->
            // Called when the user performs a touch & hold on someView.
            when (actionMode) {
                null -> {
                    // Start the CAB using the ActionMode.Callback defined earlier.
                    actionMode = activity?.startActionMode(actionModeCallback)
                    view.isSelected = true
                    true
                }
                else -> false
            }
        }
        

    Java

        someView.setOnLongClickListener(new View.OnLongClickListener() {
            // Called when the user performs a touch & hold on someView.
            public boolean onLongClick(View view) {
                if (actionMode != null) {
                    return false;
                }
    
                // Start the CAB using the ActionMode.Callback defined earlier.
                actionMode = getActivity().startActionMode(actionModeCallback);
                view.setSelected(true);
                return true;
            }
        });
        

    当您调用 startActionMode() 时,系统会返回 已创建“ActionMode”。通过将其保存在成员变量中, 可以更改上下文操作栏以响应其他事件。 在前面的示例中,ActionMode 用于确保 系统不会重新创建 ActionMode 实例(如果已创建) 活跃(在启动操作之前检查成员是否为 null) 模式。

创建弹出式菜单

显示 Gmail 应用中弹出式菜单的图片,该菜单锚定于右上角的溢出按钮。
图 4. Gmail 应用中的弹出式菜单, 锚定到右上角的溢出按钮。

PopupMenu 是锚定在 View 中的模态菜单。它显示在锚点下方 如果还有空间,则为 View;否则,在 View 上方。适合 以下:

  • 为与以下项目相关的操作提供溢出样式菜单 特定内容(例如 Gmail 的电子邮件标头),如图 4 所示。
  • 提供命令语句的另一部分,例如标为 Add 会生成一个包含不同 Add 的弹出式菜单 选项。
  • 提供类似于 Spinner 不保留永久选择。

如果您使用 XML 定义菜单,则可按照以下方法显示菜单: 弹出菜单:

  1. 使用 PopupMenu 的构造函数对其进行实例化,该构造函数采用 当前应用 Context 和 菜单锚定到的 View
  2. 使用 MenuInflater 将菜单资源膨胀到 Menu 对象 PopupMenu.getMenu()
  3. 调用 PopupMenu.show()

例如,以下按钮显示了弹出式菜单:

<ImageButton
    android:id="@+id/dropdown_menu"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:contentDescription="@string/descr_overflow_button"
    android:src="@drawable/arrow_drop_down" />

稍后,Activity 可按如下方式显示弹出式菜单:

Kotlin

findViewById<ImageButton>(R.id.dropdown_menu).setOnClickListener {
    val popup = PopupMenu(this, it)
    val inflater: MenuInflater = popup.menuInflater
    inflater.inflate(R.menu.actions, popup.menu)
    popup.show()
}

Java

findViewById(R.id.dropdown_menu).setOnClickListener(v -> {
    PopupMenu popup = new PopupMenu(this, v);
    popup.getMenuInflater().inflate(R.menu.actions, popup.getMenu());
    popup.show();
});

当用户选择菜单项或点按菜单以外的位置时,系统会关闭此菜单 区域。您可以使用以下代码监听关闭事件: PopupMenu.OnDismissListener

处理点击事件

要在用户选择菜单项时执行操作,请实现 PopupMenu.OnMenuItemClickListener 接口,并通过调用以下代码将它注册到您的 PopupMenusetOnMenuItemclickListener()。 当用户选择某个项时,系统会调用 onMenuItemClick() 回调函数。

具体可见以下示例:

Kotlin

fun showMenu(v: View) {
    PopupMenu(this, v).apply {
        // MainActivity implements OnMenuItemClickListener.
        setOnMenuItemClickListener(this@MainActivity)
        inflate(R.menu.actions)
        show()
    }
}

override fun onMenuItemClick(item: MenuItem): Boolean {
    return when (item.itemId) {
        R.id.archive -> {
            archive(item)
            true
        }
        R.id.delete -> {
            delete(item)
            true
        }
        else -> false
    }
}

Java

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;
    }
}

创建菜单组

菜单组是指一系列具有某些共同特征的菜单项。使用 您可以执行以下操作:

您可以通过在内部嵌套 <item> 元素来创建组 创建 <group> 元素,或者指定一个 带有 add() 方法。

以下是包含组的菜单资源示例:

<?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" />
    <!-- menu group -->
    <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", 两者都显示在操作栏中或同时显示在操作中 溢出。

使用可选中的菜单项

<ph type="x-smartling-placeholder">
图 5.子菜单 可选中项目。

菜单对于打开和关闭选项非常有用,可以使用菜单 复选框(表示独立选项)或单选按钮(表示相互关联的组) 专有选项。图 5 显示了一个子菜单,其中包含可通过以下项目选中的项目: 单选按钮

<ph type="x-smartling-placeholder">

您可以使用 <item> 中的 android:checkable 属性 元素,或使用 android:checkableBehavior 为整个组指定 属性位于 <group> 元素中。例如, 可使用单选按钮选中该菜单组:

<?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() 设置选中状态。显示位置 请参阅以下示例:

Kotlin

override fun onOptionsItemSelected(item: MenuItem): Boolean {
    return when (item.itemId) {
        R.id.vibrate, R.id.dont_vibrate -> {
            item.isChecked = !item.isChecked
            true
        }
        else -> super.onOptionsItemSelected(item)
    }
}

Java

@Override
public 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 会保留项目的选中状态, 当用户稍后打开菜单时,您设置的选中状态将显示为 可见。

<ph type="x-smartling-placeholder">

根据 intent 添加菜单项

有时,您希望菜单项使用 Intent, 无论是您的应用中的 activity 还是其他应用中的 activity。当您 知道要使用的 intent,并且拥有启动 您可以使用 startActivity() 调用相应的 on-item-Selected 回调方法期间 onOptionsItemSelected() 回调。

但是,如果您不确定用户的设备中包含 处理 intent,然后添加调用它的菜单项会导致 非功能性菜单项,因为 intent 可能无法解析为 activity。 为了解决这个问题,Android 允许您在以下情况下向菜单动态添加菜单项: Android 会在设备上查找可处理您的 intent 的 activity。

如需根据接受 intent 的可用 activity 添加菜单项,请执行以下操作: 以下:

  1. 使用类别定义 intent CATEGORY_ALTERNATIVECATEGORY_SELECTED_ALTERNATIVE, 以及任何其他要求
  2. 致电 Menu.addIntentOptions()。 然后,Android 会搜索任何可以执行 intent 和 将其添加到您的菜单中。

如果未安装可处理 Intent 的应用,则系统不会显示菜单 项已添加。

<ph type="x-smartling-placeholder">

具体可见以下示例:

Kotlin

override fun onCreateOptionsMenu(menu: Menu): Boolean {
    super.onCreateOptionsMenu(menu)

    // Create an Intent that describes the requirements to fulfill, to be
    // included in the menu. The offering app must include a category value
    // of Intent.CATEGORY_ALTERNATIVE.
    val intent = Intent(null, dataUri).apply {
        addCategory(Intent.CATEGORY_ALTERNATIVE)
    }

    // Search and populate the menu with acceptable offering apps.
    menu.addIntentOptions(
            R.id.intent_group,  // Menu group to which new items are added.
            0,                  // Unique item ID (none).
            0,                  // Order for the items (none).
            this.componentName, // The current activity name.
            null,               // Specific items to place first (none).
            intent,             // Intent created above that describes the requirements.
            0,                  // Additional flags to control items (none).
            null)               // Array of MenuItems that correlate to specific items (none).

    return true
}

Java

@Override
public boolean onCreateOptionsMenu(Menu menu){
    super.onCreateOptionsMenu(menu);

    // Create an Intent that describes the requirements to fulfill, to be
    // included in the 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 apps.
    menu.addIntentOptions(
         R.id.intent_group,         // Menu group to which new items are 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 the requirements.
         0,                         // Additional flags to control items (none).
         null);                     // Array of MenuItems that correlate to specific items (none).

    return true;
}

对于找到的每个提供与 intent 匹配的 intent 过滤器的 activity 则使用 intent 过滤器中的值 android:label 作为菜单项标题和应用图标作为菜单 项目图标。addIntentOptions() 方法会返回 已添加 个菜单项。

<ph type="x-smartling-placeholder">

允许将您的 activity 添加到其他菜单中

您可向其他应用提供您的活动记录对应的服务,以便 包含在其他用户的菜单中 - 颠倒前面描述的角色。

要添加到其他应用菜单中,请照常定义一个 intent 过滤器, 但包含 CATEGORY_ALTERNATIVE 或 intent 的 CATEGORY_SELECTED_ALTERNATIVE 值,或同时具有这两个值 过滤条件类别。具体可见以下示例:

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

如需详细了解如何编写 intent 过滤器,请参阅 意图和意图 过滤器