34. 【Android教程】菜单:Menu

news2025/1/12 20:53:25

作为 Android 用户,你一定见过类似这样的页面:

它就是我们今天的主角——菜单,它的使用场景和作用不用多说,几乎每个 App 都会用到它,今天我们就一起来看看 Android 提供的几种菜单类型及用法。

1. 菜单的几种类型

根据不同的业务场景和不同的样式,Android 提供了以下 3 种菜单:

  • Option Menu: 选项菜单
  • Context Menu: 上下文菜单
  • Pop-up Menu: 弹窗菜单

下面来分别介绍这 3 种菜单类型

1.1 Option Menu

选项文菜单是最常用的 Menu,可以直接通过 Android 的“菜单键”唤出,通常直接为当前 Activity 服务。在高版本的 Android 系统上是从右上角弹出,可以在里面放置一些常用的功能入口或者设置项等等高频选项。

1.2 Context Menu

上下文菜单需要绑定在一个控件之上,当我们长按这个控件的时候就会出现一个悬浮窗式的菜单,通常用于设置某个控件的属性或内容。

从字面上看和上一节学的 PopupWindow 很像,没错,它的样式确实和 PopupWindow 是一样一样的。同时它也需要绑定到一个 View 上面,然后会以一个竖直列表的形式弹出一个悬浮窗,非常适合对 View 进行设置或者提供一些相关的附加选项。

注意: Context Menu 和 Popup Menu 都需要和一个 View 绑定,但 Popup Menu 里面的选项点击不应该直接影响到 View的内容,否则应该使用 Context Menu,Popup Menu 更多的是用于 View 相关操作的扩展。

对于以上提到的 3 种类型的菜单,你都可以通过 Java 代码或者 XML 资源文件两种方式创建,但大多数情况下我强烈推荐使用XML 的形式。用 XML 可以对菜单结构一目了然,并且和逻辑代码物理隔离,更有利于我们维护。在编写完 XML 菜单资源之后,在 Java 代码中直接 inflate 加载资源文件即可。

创建菜单资源需要以下步骤:

  1. 右键点击“res”目录,依次选择:new -> Android resource directory ,如下:
  2. 在弹出的窗口中输入“menu”并选择 Resource Type 为“menu”,点击 OK:
  3. 右键点击“menu”文件夹,依次选择“New -> Menu resource file”,在 menu 目录新增一个名为“menu.xml”的菜单资源:创建完成之后,就可以开始编写 menu.xml 文件了,一个菜单资源文件通常包含以下标签:
  • menu:
    必选标签。用来定义一个菜单,菜单内所有的选项(item)都需要写在<menu/>标签内,同时它也是整个 menu 资源文件的根节点。

  • item:
    必选标签。用来创建一个菜单项,每一个<item/>标签代表 menu 中的一个选项,另外在 <item/>中我们还可以嵌套定义<menu/>节点,以此来创建一个子菜单。

  • group:
    可选标签。用来将多个<item/>标签做分组,它用来对菜单里的选项进行分类,这样同类型的选项可以共享一些属性,增强选项类别。

在了解了菜单资源标签之后,我们就可以简单编写一个菜单资源了,代码非常简单如下:

<?xml version="1.0" encoding="utf-8"?>
  <menu xmlns:android="http://schemas.android.com/apk/res/android">
      <item android:id="@+id/main_menu"
              android:title="我要学习客户端开发"
              android:icon="@drawable/ic_launcher" >

              <!-- 添加客户端子菜单 -->
              <menu>
                  <item android:id="@+id/submenu1"
                      android:title="学习 Android"
                      android:icon="@drawable/ic_launcher"/>
                  <item android:id="@+id/submenu2"
                      android:title="学习 iOS"
                      android:icon="@drawable/apple" />
              </menu>
      </item>
  </menu>

其中<item/>标签支持几种属性来配置样式或者行为,常用的属性比较好理解,主要有以下 2 种:

  • android:id:
    菜单项的资源 ID,用来唯一标识某个选项,后续可以通过 ID 来判断用户点击的是哪个菜单项。
  • android:icon:
    设置菜单项对应的图标
  • android:title:
    设置菜单项的内容

3. 几种菜单的使用

在第 2 小节我们已经通过 XML 的形式完成了菜单内容的设置,接着需要在 Activity 中编写逻辑并加载菜单资源,以下就根据不同的类型分别演示如何完成菜单的加载及使用。

3.1 Option Menu 示例

3.1.1 加载 Option Menu 资源

为了使用 Option Menu,我们需要在 Activity 中复写onCreateOptionsMenu()方法:

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

当 Activity 创建 Option Menu 的时候系统会回调此函数,我们只需要在里面 inflate 我们的菜单资源即可,其中getMenuInflater()用来获取一个“MenuInflater”对象,我们可以用它来加载一个 menu 资源文件——menu.xml。

3.1.2 处理菜单项的点击事件

当用户在菜单中点击了某个选项之后,Android 系统会回调onOptionsItemSelected()方法,并传入被选菜单项的 Menu 实例。我们可以通过 Menu 实例的getItemId()方法拿到菜单项对应的唯一 ID(通过<item/>标签的 android:id 属性设置的),从而判断用户选择的是哪一项,进而执行相应的逻辑,代码如下:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
     // 根据点击的选项处理不同的逻辑
    switch (item.getItemId()) {
        case R.id.menu:
            // 点击主菜单
            return true;
        case R.id.submenu1:
             // 点击子菜单1
            return true;
        case R.id.submenu2:
             // 点击子菜单2
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
}

**注意:**在你成功处理了菜单项的点击事件之后(我们通常称之为消费),你需要在函数的末尾返回“true”,如果没有消费那么可以返回false,不过建议调用super.onOptionsItemSelected(item)将本次点击事件交给上层处理(上层的默认实现也是false)。

3.2 Context Menu 示例

3.2.1 加载 ContextMenu

加载一个 ContextMenu 通常需要以下步骤:

  1. 调用registerForContextMenu()传入一个 View,来为该 View 注册一个Context Menu,从此该 View 就和一个 OptionMenu 绑定;
  2. 在 Activity 中复写onCreateContextMenu()方法,当用户长按你注册过的 View,Android 系统就会回调此方法,我们可以在这里进行 menu 资源的加载。

其实逻辑和 Option Menu 类似,但是因为需要绑定 View 所以多了一个注册操作,加载代码如下:

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

onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo)方法需要传入 3 个参数,分别是:

  • ContextMenu menu: 菜单对象,类似 OptionMenu 里面的 Menu 对象
  • View v: 与 Context Menu 绑定的 View 对象
  • ContextMenuInfo menuInfo: 包含与被选项的一些附加信息

注意: 如果当前 Activity 有多个 View 都有 Context Menu,那么需要通过这几个参数来判断当前触发的是哪个 View 相关的 Context Menu

3.2.2 处理 Context Menu 选项的点击事件

当用户点击上下文菜单项的时候,系统会回调onContextItemSelected()方法,所以我们可以在方法里实现相应的处理逻辑。如下:

@Override
  public boolean onContextItemSelected(MenuItem item) {
            // 处理 Context Menu 选项的点击事件
      }
  }

3.3.1 展示 Popup Menu

和 Context Menu 类似,Popup Menu 也需要和一个 View 绑定,但二者的加载过程有些不同。加载一个 Popup Menu 需要经过 3 个步骤:

  • 调用 PopupMenu 的构造器,传入当前 Application 的上下文对象,待绑定的 View;
  • 调用getMenuInflater()获取 MenuInflater对象,通过它将菜单资源装载入 PopupMenu 的 Menu 实例中;
  • 调用 PopupMenu 对象的show()弹出菜单。

加载代码如下:

PopupMenu popupMenu = new PopupMenu(this,view);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu,popupMenu .getMenu());
popup.show();
3.3.2 监听 Popup Menu 的点击事件

为了监听 Popup Menu 的点击事件,我们需要在 Activity 中实现PopupMenu.OnMenuItemClickListener接口并通过setOnMenuItemclickListener()方法注册 Popup Menu。这样一来,当用户点击菜单项的时候,Android 系统会回调 Activity 的onMenuItemClick()方法,在当中处理点击事件即可。

4. 完整示例代码

通过以上针对每个类型 Menu 的讲解,大家对菜单的创建和使用应该都比较清楚了,下面我们通过一个完整的示例来演示一下 3 种菜单的使用。

4.1 编写 menu 资源

在第 2 小节中我们详细介绍了 menu 资源,它包括<menu/><item/><group/>三种标签,为了演示方便我们直接采用第 2 小节中的菜单资源。

4.2 编写布局

菜单本身并不涉及到布局的编写,我们只需要两个 View,一个绑定给 Context Menu,一个给 Popup Menu:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/tv_context"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingBottom="30dp"
        android:text="我这里有 Context Menu"
        android:textSize="20sp" />

    <Button
        android:id="@+id/bt_popup"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="pop"
        android:text="我这里有 Popup Menu" />
</LinearLayout>

4.3 编写 Activity

最后就可以编写 Activity 了,其中要做的就是为 Menu 做资源加载,并接收点击回调即可:

package com.emercy.myapplication;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.PopupMenu;
import android.view.ContextMenu;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;

public class MainActivity extends AppCompatActivityimplements PopupMenu.OnMenuItemClickListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		// 为 TextView 注册 Context Menu
		registerForContextMenu(findViewById(R.id.tv_context));
    }


    // 加载 Option Menu
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater menuInflater = getMenuInflater();
		menuInflater.inflate(R.menu.menu, menu);
		return true;
    }
    // 接收 Option Menu 的点击
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
		return onItemClick(item);
    }

    // 加载 Context Menu
    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
		super.onCreateContextMenu(menu, v, menuInfo);
		MenuInflater menuInflater = getMenuInflater();
		menuInflater.inflate(R.menu.menu, menu);
    }

    // 接收 Context Menu 的点击
    @Override
    public boolean onContextItemSelected(MenuItem item) {
		return onItemClick(item);
    }
    
    // 加载 Popup Menu
    public void pop(View v){
		PopupMenu popup = new PopupMenu(this, v);
		MenuInflater menuInflater = getMenuInflater();
		menuInflater.inflate(R.menu.menu, popup.getMenu());
		popup.show();

    }

    // 接收 Popup Menu 的点击
    @Override
    public boolean onMenuItemClick(MenuItem item) {
		return onItemClick(item);
    }
    
    private boolean onItemClick(MenuItem item) {
    	switch (item.getItemId()) {
		case R.id.main_menu:
			Toast.makeText(this, "选择了客户端开发", Toast.LENGTH_SHORT).show();
			break;
		case R.id.submenu1:
			Toast.makeText(this, "选择学习 Android", Toast.LENGTH_SHORT).show();
			break;
		case R.id.submenu2:
			Toast.makeText(this, "选择学习 iOS", Toast.LENGTH_SHORT).show();
			break;
		}
		return true;
	}
}

针对每个菜单都分别有“加载资源”和“处理点击”两种操作,另外由于每个菜单的处理逻辑都一样,为了增强代码复用性我单独拎出了一个函数onItemClick()专门用于统一处理点击事件。
最终样式如下(在不同的设备上可能会有所不同):

Option Menu 的子菜单:

Context Menu 的子菜单:

Popup Menu 的主菜单:

5. 小结

本节介绍了 Android 提供的几种菜单:Option Menu 通常用来提供 Activity 相关的选项,Context Menu 通常用来针对某个 View 进行设置,而 Popup Menu 用来设置某个 View 的属性或者展示一些附加功能。使用的步骤大体相同,在一个完整 App 的开发中,Menu 是必不可少的部分,希望大家能够很好的掌握本节内容。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1609379.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[Algorithm][滑动窗口][无重复字符的最长字串][最大连续的一个数 Ⅲ][将x减到0的最小操作数]详细讲解

目录 1.无重复字符的最长字串1.题目链接2.算法原理详解3.代码实现 2.最大连续的一个数 Ⅲ1.题目链接2.算法原理详解3.代码实现 3.将x减到0的最小操作数1.题目链接2.算法原理详解3.代码实现 1.无重复字符的最长字串 1.题目链接 无重复字符的最长字串 2.算法原理详解 研究的对…

美化博客文章(持续更新)

&#x1f381;个人主页&#xff1a;我们的五年 &#x1f50d;系列专栏&#xff1a;游戏实现&#xff1a;贪吃蛇​​​​​​ &#x1f337;追光的人&#xff0c;终会万丈光芒 前言&#xff1a; 该文提供我的一些文章设计的一些方法 目录 1.应用超链接 1.应用超链接

URL GET +号后台接收成空格

问题&#xff1a;参数spdmwhbs001 其中包含URL特殊符号 如果用GET请求方式不做任何不处理那么浏览器自动将转为%20 请求链接为 details?spdmwhbs%20001&limitKcysType1 后台接收到的参数为 whbs 001 &#xff0c;自动将号转成空格了。 尝试解决&#xff08;失败&#…

使用FastDDS编译IDL文件

1.安装FastDDS环境 Ubuntu22.04 1.1安装依赖的软件 sudo apt-get update //基础工具安装 sudo apt install cmake g python3-pip wget git //Asio 是一个用于网络和低级 I/O 编程的跨平台C库&#xff0c;它提供了一致的 异步模型。 TinyXML2是一个简单&#xff0c;小巧&…

400电话如何对接配置SIP

400电话对接配置SIP的基本步骤 要配置400电话对接SIP&#xff0c;通常需要遵循以下基本步骤&#xff1a; 注册和认证&#xff1a;首先需要在相应的云通信平台上注册账号&#xff0c;并进行企业实名认证。 开通语音服务&#xff1a;在通过认证后&#xff0c;需要开通语音服务&…

C# winform s7.net expected 22 bytes.”

S7.Net.PlcException:“Received 12 bytes: 32-02-00-00-00-00-00-00-00-00-81-04, expected 22 bytes.” 原因是博图的连接机制未勾选

Java编程题 | 数组元素交换

大家可以关注一下专栏&#xff0c;方便大家需要的时候直接查找&#xff0c;专栏将持续更新~ 题目描述 编写一个Java程序&#xff0c;输入一个整数数组&#xff0c;将最大的元素与第一个元素交换&#xff0c;最小的元素与最后一个元素交换&#xff0c;然后输出修改后的数组…

数据结构从入门到实战——顺序表的应用

目录 一、基于动态顺序表实现通讯录 二、代码实现 2.1 通讯录的初始化 2.2 通讯录的销毁 2.3 通讯录的展示 2.4 通讯录添加联系人信息 2.5 通讯录删除联系人信息 2.6 通讯录修改联系人信息 2.7 通讯录的查找联系人信息 2.8 将通讯录中联系人信息保存到文件中 2.9…

【Qt】设置QT标准对话框为中文字体

设置QT标准对话框为中文字体 一、问题二、解决方法1、找到Qt内置的翻译文件 qt_zh_CN.qm2、在代码中加载该文件 一、问题 在Qt中我们使用的标准对话框都是英文&#xff0c;例如下面的 字体选择对话框&#xff0c;但是实际中我们需要构建的是中文对话框。 所以我们需要使用Qt官…

【redis】hash和list常用命令

hash类型 Redis自身已经是键值对结构了。Redis自身的键值对就是通过哈希的方式来组织的。 把key这一层组织完成之后,到了value这一层。value的其中一种类型还可以再是哈希。哈希类型中的映射关系通常称为field-value,用于区分Redis整体的键值对(key-value)。注意这里的 value…

为什么创业总是小部分人能成功?

每年都有大批量应届生等待就业&#xff0c;同时&#xff0c;也有一大批大龄中青人正在面临失业。在这种焦虑&#xff0c;内卷的氛围下&#xff0c;就会激发一波又一波的人走上创业的道路。想靠创业改变命运。辞职之后&#xff0c;第一时间能想到的创业方式要么就是就是 开个奶茶…

阿里云ECS服务器安装docker

首先查看阿里云ECS的服务器的版本 cat /etc/redhat-release如果是Alibaba Cloud Linux release 3,请执行以下命令 添加docker-ce的dnf源。 sudo dnf config-manager --add-repohttps://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo安装Alibaba Cloud Linux 3专…

【若依前后端分离】仪表盘绘制

示例&#xff1a; 代码&#xff1a; InstrumentPanel.vue组件 <template><div><!-- 在这里放置你的图表组件 --><div ref"echarts" style"width: 100%; height: 400px;"></div></div> </template><script&g…

如何将你的iOS应用成功上架App Store(图文详解)

上架基本需求资料 1、苹果开发者账号&#xff08;如还没账号先申请- 苹果开发者账号申请教程&#xff09; 2、开发好的APP 通过本篇教程&#xff0c;可以学习到ios证书申请和打包ipa上传到appstoreconnect.apple.com进行TestFlight测试然后提交审核的完整流程&#xff01; …

基于javaspringboot实现的垃圾分类网站

开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09; 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven…

Android RecyclerView的LayoutManager配置

RecyclerView的item布局方式依赖于其配置的布局管理器。不同的布局管理器可以实现不同的界面效果。 LayoutManager介绍 RecyclerView可以通过setLayoutManager设置布局管理器&#xff0c;该方法的源码如下&#xff1a; /*** Set the {link LayoutManager} that this RecyclerV…

YOLOv5 / YOLOv7 / YOLOv8 / YOLOv9 / RTDETR -gui界面-交互式图形化界面

往期热门博客项目回顾&#xff1a;点击前往 计算机视觉项目大集合 改进的yolo目标检测-测距测速 路径规划算法 图像去雨去雾目标检测测距项目 交通标志识别项目 yolo系列-重磅yolov9界面-最新的yolo 姿态识别-3d姿态识别 深度学习小白学习路线 AI健身教练-引体向上…

ESP32S3在VScode中使用USB口调试

ESP32S3在VScode中使用USB口调试 安装USB驱动修改工程的配置文件launch.jsonsettings.json 启动GDB Server 安装USB驱动 在powershell中输入下面指令&#xff1a; Invoke-WebRequest https://dl.espressif.com/dl/idf-env/idf-env.exe -OutFile .\idf-env.exe; .\idf-env.exe…

Windows 平台上面管理服务器程式的高级 QoS 策略

在 Windows 平台上面&#xff0c;目前有两个办法来调整应用程式的 QoS 策略设置&#xff0c;一种是通过程式设置&#xff0c;一种是通过 “Windows 组策略控制”。 在阅读本文之前&#xff0c;您需要先查阅本人以下的几篇文献&#xff0c;作为前情提示&#xff1a; VC Windows…

Redis进阶——点赞和点赞排行

目录 发布达人探店笔记实现步骤 查看探店笔记点赞功能问题分析&#xff1a;功能完善具体实现 点赞排行榜实现需求实现步骤 发布达人探店笔记 实现类似于大众点评的发布个人笔记的效果 实现步骤 准备数据表如下&#xff1a; SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS 0;…