Android 动态更新Menu菜单

news/2024/5/6 15:07:50/文章来源:https://blog.csdn.net/u012514113/article/details/126665826

1. 需求描述

        Android Menu菜单是比较常见的功能,在ActionBar  or ToolBar上显示,点击更多(3个点),会有下拉列表菜单展示,  在工作项目中有个小需求改动: 在 ToolBar上添加一个图标,点击后会切换图标状态,界面也会显示对应内容,这也是本篇文章要讲的是如何动态更新Menu菜单。

        首先,我们来看看效果图:

1. 当点击网格图标时,显示为网格模式

 2. 当点击列表图标时,显示为列表模式

 3. 点击更多图标时,显示更多菜单列表:设置   关于  测试

2. 基础知识

        在写代码之前,先来复习一下Menu的基础知识,具体可以看官方文档:Menus  |  Android Developers

菜单xml编写例子:

<menu 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"tools:context="com.example.menutest.MainActivity"><itemandroid:id="@+id/sub_menu_grid"android:title="网格视图"android:icon="@drawable/ic_menu_view_grid"app:showAsAction="always"/><itemandroid:id="@+id/sub_menu_list"android:title="列表视图"android:icon="@drawable/ic_menu_view_list"app:showAsAction="always"/><itemandroid:id="@+id/action_settings"android:orderInCategory="100"android:title="设置"app:showAsAction="never" /><itemandroid:id="@+id/action_about"android:orderInCategory="200"android:title="关于"app:showAsAction="never" /><itemandroid:id="@+id/action_test"android:orderInCategory="300"android:title="测试"app:showAsAction="never" /></menu>

<item>是我们主要需要关注的元素,它的常见属性如下:

    android:id:     菜单项(MenuItem)的唯一标识(必须定义)
    android:icon: 菜单项的图标(可选)
    android:title: 菜单项的标题(必选)
    android:showAsAction:指定菜单项的显示方式。常用的有ifRoom、never、always、withText,多个属性值之间可以使用|隔开。

指定菜单的显示方式:

always:菜单项永远不会被收纳到溢出菜单中,因此在菜单项过多的情况下可能超出菜单栏的显示范围。

ifRoom:在空间足够时,菜单项会显示在菜单栏中,否则收纳入溢出菜单中。

withText:无论菜单项是否定义了icon属性,都只会显示它的标题,而不会显示图标。使用这种方式的菜单项默认会被收纳入溢出菜单中。

never:菜单项永远只会出现在溢出菜单中。

我们通过上面的3张图片,在Toolbar上面显示有两类菜单:

1. 比如网格和列表菜单,在菜单栏上定义为一直显示(always),我们称它为常驻菜单

2. 另一种会被集中放置到溢出菜单中(就是菜单栏右侧的3个小点图标图标)

3. 菜单加载

        菜单加载,有两个相关API 

  1.  onCreateOptionsMenu(Menu menu)

      此方法在初次加载菜单时,会调用一次。

2.  onPrepareOptionsMenu(Menu menu)

      此方法应用场景:在运行时更改菜单项,我们看看官网的描述:

在运行时修改的选项菜单:

系统调用onCreateOptionsMenu方法后,将保留创建的Menu实例。除非菜单由于某些原因而失效,否则不会再次调用onCreateOptionsMenu。因此,我们只应该使用onCreateOptionsMenu来创建初始菜单状态,而不应使用它在Activity生命周期中对菜单执行任何更改。

如果需要根据在Activity生命周期中发生的某些事件修改选项菜单,则应该通过onPrepareOptionsMenu方法实现。这个方法的参数中有一个Menu对象(即旧的Menu对象),我们可以使用它对菜单执行修改,如添加、移除、启用或禁用菜单项。(Fragment同样提供onPrepareOptionsMenu方法,只是不需要提供返回值)

需要注意:在Android 3.0及更高版本中,当菜单项显示在应用栏中时,选项菜单被视为始终处于打开状态,说的就是常驻菜单。发生事件时,如果要执行菜单更新,则必须调用 invalidateOptionsMenu来请求系统调用onPrepareOptionsMenu方法

对于上句话我的理解如下:

1. 对于常驻菜单,如果你想动态修改菜单的话,就必须调用 invalidateOptionsMenu() 方法去更新,为什么呢? 因为调用 invalidateOptionsMenu方法后,会重新执行一遍 onCreateOptionsMenu 和 onPrepareOptionsMenu这两个方法。

2. 对于溢出菜单,如果你想动态修改菜单的话,只需要在onPrepareOptionsMenu方法中实现即可,为什么呢?

    当你点击 更多(3个小点)图标的时候,就会回调onPrepareOptionsMenu方法

4. 需求实现

        有了上面理论做支持,具体结合需求,网格和列表菜单属于常驻菜单,所以必须先要调用invalidateOptionsMenu()方法,然后在onPrepareOptionsMenu去写动态更新状态的代码

       图三中,关于属于溢出菜单,需求: 关于 菜单不能点击,所以也是在onPrepareOptionsMenu中去写动态更新状态的代码

好了,我把代码展示出来:

public class MainActivity extends AppCompatActivity {//默认为网格模式private boolean isShowGridModeIcon = true;//网格菜单 和 列表菜单private MenuItem gridMenuItem;private MenuItem listMenuItem;//用字符串来表示当前的文件列表显示模式private TextView viewModeStatus;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Toolbar toolbar = findViewById(R.id.toolbar);setSupportActionBar(toolbar);viewModeStatus = findViewById(R.id.textview_refresh);}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// Inflate the menu; this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.menu_main, menu);Log.e("test", "=====MenuTest onCreateOptionsMenu=====");gridMenuItem = menu.findItem(R.id.sub_menu_grid);listMenuItem = menu.findItem(R.id.sub_menu_list);return true;}@Overridepublic boolean onPrepareOptionsMenu(Menu menu) {Log.e("test", "=====MenuTest onPrepareOptionsMenu=xxxx====");MenuItem aboutMenuItem = menu.findItem(R.id.action_about);// (3个点)【更多】菜单中把 关于 设置为不可点击aboutMenuItem.setEnabled(false);if (isShowGridModeIcon) {gridMenuItem.setVisible(true);listMenuItem.setVisible(false);viewModeStatus.setText("当前为网格模式");} else {gridMenuItem.setVisible(false);listMenuItem.setVisible(true);viewModeStatus.setText("当前为列表模式");}return super.onPrepareOptionsMenu(menu);}@Overridepublic boolean onOptionsItemSelected(MenuItem item) {// Handle action bar item clicks here. The action bar will// automatically handle clicks on the Home/Up button, so long// as you specify a parent activity in AndroidManifest.xml.int id = item.getItemId();Log.e("test", "=====MenuTest onOptionsItemSelected= sssss ====");//noinspection SimplifiableIfStatementif (id == R.id.action_settings) {return true;} else if (id == R.id.sub_menu_grid) {/*1. 点击网格图标,界面中文件布局显示变成网格模式*///伪代码:setViewMode(State.MODE_GRID);isShowGridModeIcon = false;/*2. 图标变成切换list图标*/invalidateOptionsMenu();} else if (id == R.id.sub_menu_list) {/*1.点击列表图标,界面中文件布局显示变成列表模式*///伪代码:setViewMode(State.MODE_LIST);isShowGridModeIcon = true;/*2. 图标变成切换grid图标*/invalidateOptionsMenu();}return super.onOptionsItemSelected(item);}
}

代码中加了打印log
1.  在桌面上启动apk的时候,打印log如下:

21900 21900 E test    : =====MenuTest onCreateOptionsMenu=====
21900 21900 E test    : =====MenuTest onPrepareOptionsMenu=xxxx====

2. 点击网格模式菜单时,打印log如下:

21900 21900 E test    : =====MenuTest onOptionsItemSelected= sssss ====
21900 21900 E test    : =====MenuTest onCreateOptionsMenu=====
21900 21900 E test    : =====MenuTest onPrepareOptionsMenu=xxxx====

    如上分析,在onOptionsItemSelected方法中点击响应时,调用了invalidateOptionsMenu方法,所以会重新走一遍onCreateOptionsMenu, onPrepareOptionsMenu。

3. 点击(3个点)更多菜单时,打印log如下:

21900 21900 E test    : =====MenuTest onPrepareOptionsMenu=xxxx====

     如上分析, 对于溢出菜单类型,点击更多菜单时,只会回调onPrepareOptionsMenu方法

5. 总结

        本篇文章讲解了动态菜单更新显示的过程,也是对menu菜单的一个小结,对于同类需求,可以仿照此demo,整个Demo代码我上传到这里:Android动态更新Menu菜单-Android文档类资源-CSDN下载

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

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

搭建简易Spring-ioc框架

SpringFrameWork系列1 文章目录SpringFrameWork系列1一、谈谈对Spring的认识二、控制反转(ioc)的作用2.1 ioc的优缺点三、搭建Spring-ioc框架一、谈谈对Spring的认识 Spring是一个开源框架&#xff0c;是为了解决企业应用开发的复杂性而产生的。 特征&#xff1a;轻量级别&…

第66章 基于.Net(Core)x框架的开源分页插件

1 Jquery DataTable 分页插件 Jquery DataTable分页插件是完全基于javaScript的&#xff0c;所以它是跨框架的&#xff0c;即不管你使用的是那种语言&#xff0c;那种平台开发网站程序&#xff0c;基本上都能通过使用Jquery DataTable分页插件实现分页操作。 在nopCommerce开发…

TASK04分组|joyfulpandas

目录一、分组模式及其对象1. 分组的一般模式2. 分组依据的本质【练一练】【END】3.Groupby对象【练一练】【END】 size4. 分组的三大操作二、聚合函数1. 内置聚合函数【练一练】【END】2. agg方法【练一练】【练一练】【END】三、变换和过滤1. 变换函数与transform方法【练一练…

02|一条MySQL更新语句是如何执行的

02|一条MySQL更新语句是如何执行的 update T set cc1 where ID2;其实一条更新语句的执行操作和查询语句的执行操作基本相同->一条SQL查询语句是如何查询的&#xff1f;&#xff0c;唯一不同的是一条更新语句在执行过程中需要涉及到两个日志操作&#xff08;redo log、binlo…

四、集合

四、集合 集合和数组区别 &#xff08;1&#xff09;数组定长&#xff0c;集合不定长&#xff08;2&#xff09;数组可存基础数据类型和引用类型&#xff0c;集合只能存引用类型 位置&#xff1a;java.util.*; 这是一位仁兄的笔记&#xff0c;师出同门&#xff0c;点我跳转~ 1、…

高级js 面向对象 和面向过程 三种函数

判断数据类型 // 创建一个Cat对象&#xff0c;属性:颜色&#xff0c;品种&#xff0c;行为:吃&#xff0c;跑&#xff0c;捉老鼠var Cat new Object() //new一个对象Cat.catys red //属性Cat.catname cat //对象名// 行为Cat.catxw function () {console.log("喜欢跑&…

Python3,我用这种方式讲解python模块,80岁的奶奶都说能理解。建议收藏 ~ ~

Python模块讲解1、引言2、python模块详解2.1 含义2.2 代码示例2.3 进阶3、总结1、引言 小屌丝&#xff1a;鱼哥&#xff0c;你看天上的月亮越来越圆了。 小鱼&#xff1a;唉~ 又是一年团圆夜&#xff0c;又是一年中秋节。 小屌丝&#xff1a;嘿嘿&#xff0c;可不滴&#xff0…

二维凸包问题

什么是二维凸包 假设墙上顶一组钉子&#xff0c;这些钉子的集合为X&#xff0c;我们用橡皮筋围住这些钉子&#xff0c;橡皮筋的形状就是凸包(来源于网络)。 向量的叉乘 对于两个向量pq⃗\vec{pq}pq​和qr⃗\vec{qr}qr​ 如果pq⃗\vec{pq}pq​和qr⃗\vec{qr}qr​的叉积结果大于0…

分销商城小程序开发运营逻辑是什么?

商城分销现在用的人比较多&#xff0c;其中用的最多的差不多就是二级分销、三级分销&#xff0c;除了这两种分销方式&#xff0c;还有一种是一级分销&#xff0c;不过裂变效果可能不如二级分销、三级分销要好&#xff0c;所以用的人不是特别的多。 二级分销跟三级分销的逻辑都差…

C++PrimerPlus跟读记录【第五章】循环和关系表达式

1、for 循环 for(initialization; test-expression; updata-expression)test-expression 关系表达式&#xff0c;结果强制为bool类型&#xff0c;true or false。 表达式和语句 C表达式是 值 或 值与运算符的组合&#xff0c;每个表达式都有值。表达式只要加上分号&#xff0…

剑指offer32-42字符串数组的应用

剑指 Offer II 032. 有效的变位词 给定两个字符串 s 和 t &#xff0c;编写一个函数来判断它们是不是一组变位词&#xff08;字母异位词&#xff09;。t 是 s的变位词等价于「两个字符串不相等且两个字符串排序后相等」 注意&#xff1a;若 s 和 t 中每个字符出现的次数都相同…

QT QTextEdit富文本插入字体-表格-编号-图片-查找-语法高亮功能

QT QTextEdit富文本插入字体-表格-编号-图片与查找功能&#xff0c;输入char 自动变成蓝色-语法高亮功能 QTQTextEdit富文本插入字体-表格-编号-图片-查找-语法高亮功能.rar-QT文档类资源-CSDN下载QTQTextEdit富文本插入字体-表格-编号-图片-查找-语法高亮功能.rarhttps:/更多…

Vue使用脚手架(ref、props、mixin、插件、scoped)(七)

系列文章目录 第一章&#xff1a;Vue基础知识笔记&#xff08;模板语法、数据绑定、事件处理、计算属性&#xff09;&#xff08;一&#xff09; 第二章&#xff1a;Vue基础知识&#xff08;计算属性、监视属性、computed和watch之间的区别、绑定样式&#xff09;&#xff08;…

四、 java的对象和类

四、 java的对象和类 对象&#xff08;Object&#xff09;&#xff1a;对象是类的一个实例&#xff0c;有状态和行为。例如&#xff0c;一条狗是一个对象&#xff0c;它的状态有&#xff1a;颜色、名字、品种&#xff1b;行为有&#xff1a;摇尾巴、叫、吃等。类&#xff08;c…

物理服务器安装CentOS 7操作系统

目录 1、下载系统镜像 2、制作安装盘 2.1 方法一&#xff1a;光盘制作 2.2 方法二&#xff1a;U盘制作 3、更改bios启动顺序 4、安装CentOS 7操作系统 4.1 安装命令选择&#xff0c;及常见错误解决 4.2 语言选择 4.3 时区选择 4.4 软件选择 4.5 安装位置选择 4.6 手…

猿创征文|【C++游戏引擎Easy2D】学C++还不会绘制一个简单的二维图形?一篇文章教会你

&#x1f9db;‍♂️iecne个人主页&#xff1a;&#xff1a;iecne的学习日志 &#x1f4a1;每天关注iecne的作品&#xff0c;一起进步 &#x1f4aa;学C必看iecne 本文专栏&#xff1a;【C游戏引擎】. &#x1f433;希望大家多多支持&#x1f970;一起进步呀&#xff01; ✨前…

Apache Maven 3.6.0的下载安装和环境配置(详细图解+不限速下载链接)

标题工具/原料 apache-maven-3.6.0 下载地址 云盘不限速下载 或者进入官网按下图下载 方法/步骤一 安装 打开压缩包&#xff0c;将maven压缩包解压至软件安装处&#xff0c;建议D根目录或其他&#xff0c;记住安装位置 类似于 方法/步骤二 环境变量配置 变量 1.新建变…

Eolink 通过可信云权威认证,数据保护能力业内领先!

Eolink 正式通过由中国信息通信研究院组织发起的可信云评估考核&#xff0c;在数据安全保障领域获得权威认证&#xff0c;并荣获 “企业级 SaaS 服务” 认证证书。 在云时代&#xff0c;保护用户数据安全、预防隐私泄露是数字化企服厂商的重中之重。Eolink 作为一个 API 在线管…

计算机毕业设计ssm+vue基本微信小程序的个人健康管理系统

项目介绍 首先,论文一开始便是清楚的论述了小程序的研究内容。其次,剖析系统需求分析,弄明白“做什么”,分析包括业务分析和业务流程的分析以及用例分析,更进一步明确系统的需求。然后在明白了小程序的需求基础上需要进一步地设计系统,主要包罗软件架构模式、整体功能模块、数…

IIC协议详解

文章目录1 IIC简介2 IIC物理层2.1 IIC硬件2.2 IIC协议特点3 IIC协议层4数据传输4.1 IIC写数据4.2 IIC读数据1 IIC简介 IIC(Inter&#xff0d;Integrated Circuit)总线是一种由 NXP&#xff08;原 PHILIPS&#xff09;公司开发的两线式串行总线&#xff0c; 用于连接微控制器及其…