Android菜单详解——理解android中的Menu
前言
今天看了pro android 3中menu这一章,对Android的整个menu体系有了进一步的了解,故整理下笔记与大家分享。
PS:强烈推荐《Pro Android 3》,是我至今为止看到的最好的一本android书,中文版出到《精通Android 2》。
理解Android的菜单
菜单是许多应用程序不可或缺的一部分,Android中更是如此,所有搭载Android系统的手机甚至都要有一个"Menu"键,由此可见菜单在Android程序中的特殊性。Android SDK提供的菜单有如下几种:
- 选项菜单:最常规的菜单,android中把它叫做option menu
- 子菜单:android中点击子菜单将弹出悬浮窗口显示子菜单项。子菜单不支持嵌套,即子菜单中不能再包括其他子菜单。
- 上下文菜单:android中长按视图控件后出现的菜单,windows点击右键弹出的菜单即上下文菜单
- 图标菜单:这个比较简单,就是带icon的菜单项,需要注意的是子菜单项、上下文菜单项、扩展菜单项均无法显示图标。
- 选择菜单(alternative menu):用的比较少,以后单独介绍,本文先跳过(其实是我还没弄明白啦o(≧v≦)o~~)
- 扩展菜单:选项菜单最多只能显示6个菜单项,超过6个时,第6个菜单项会被系统替换为一个叫“更多”的子菜单,原来显示不下的菜单项都作为“更多”菜单的子菜单项。如下图:
第6个菜单项自动变为“更多” 点击“更多”显示其他菜单项
Android3.0又引入了一个叫action bar的东西,本文不做讲解,大家自己google。
android.view.Menu接口代表一个菜单,android用它来管理各种菜单项。注意我们一般不自己创建menu,因为每个Activity默认都自带了一个,我们要做的是为它加菜单项和响应菜单项的点击事件。android.view.MenuItem代表每个菜单项,android.view.SubMenu代表子菜单。其三者的关系可以用下图来表示
上面说过,每个activity包含一个菜单,一个菜单又能包含多个菜单项和多个子菜单,子菜单其实也是菜单(因为它实现了Menu接口),因此子菜单也可以包含多个菜单项。SubMenu继承了Menu的addSubMenu()方法,但调用时会抛出运行时错误。OnCreateOptionsMenu()和OnOptionsMenuSelected()是activity中提供了两个回调方法,用于创建菜单项和响应菜单项的点击。
创建options menu
之前提到,Android的activity已经为我们提前创建好了android.view.Menu对象,并提供了回调方法onCreateOptionsMenu(Menu menu)供我们初始化菜单的内容。该方法只会在选项菜单第一次显示的时候被执行,如果你需要动态改变选项菜单的内容,请使用 onPrepareOptionsMenu(Menu)
。
@Overridepublicboolean onCreateOptionsMenu(Menu menu) {// 调用父类方法来加入系统菜单// 虽然目前android还没有系统菜单,但是为了兼容到以后的版本,最好加上super.onCreateOptionsMenu(menu); // 添加菜单项(多种方式)// 1.直接指定标题 menu.add("菜单项1");// 2.通过资源指定标题 menu.add(R.string.menuitem2);// 3.显示指定菜单项的组号、ID、排序号、标题 menu.add(1, //组号 Menu.FIRST, //唯一的ID号 Menu.FIRST, //排序号"菜单项3"); //标题 // 如果希望显示菜单,请返回truereturntrue;}
add(int groupId, int itemId, int order, CharSequence title)
上面的代码演示了添加菜单项的3种方法,下面解释下第三种方法。其中,第一个参数是组号,android中你可以给菜单分组,以便快速地操作同一组的菜单。第二个参数指定每个菜单项的唯一ID号,你可以自己指定,也可以让系统来自动分配,在响应菜单时你需要通过ID号来判断哪个菜单被点击了。因此常规的做法是定义一些ID常量,但在android中有更好的方法,就是通过资源文件来引用,这个之后介绍。第三个参数代表菜单项显示顺序的编号,编号小的显示在前面。
给菜单项分组
@Overridepublicboolean onCreateOptionsMenu(Menu menu) {super.onCreateOptionsMenu(menu);// 添加4个菜单项,分成2组int group1 =1;int gourp2 =2; menu.add(group1, 1, 1, "item 1"); menu.add(group1, 2, 2, "item 2"); menu.add(gourp2, 3, 3, "item 3"); menu.add(gourp2, 4, 4, "item 4");// 显示菜单returntrue;}
你可以向上面这样给菜单项分组,分组之后就能使用menu中提供的方法对组进行操作了,如下:
menu.removeGroup(group1); //删除一组菜单menu.setGroupVisible(gourp2, visible); //设置一组菜单是否可见menu.setGroupEnabled(gourp2, enabled); //设置一组菜单是否可点menu.setGroupCheckable(gourp2, checkable, exclusive); //设置一组菜单的勾选情况
响应菜单项
android提供了多种响应菜单项的方式,下面一一介绍
1、通过onOptionsItemSelected方法
使用的最多方法是重写activity类的 onOptionsItemSelected(MenuItem)
回调方法,每当有菜单项被点击时,android就会调用该方法,并传入被点击菜单项。
@Overridepublicboolean onOptionsItemSelected(MenuItem item) {switch (item.getItemId()) {//响应每个菜单项(通过菜单项的ID)case1:// do something herebreak;case2:// do something herebreak;case3:// do something herebreak;case4:// do something herebreak;default://对没有处理的事件,交给父类来处理returnsuper.onOptionsItemSelected(item); }//返回true表示处理完菜单项的事件,不需要将该事件继续传播下去了returntrue;}
以上代码可作为使用onOptionsItemSelected方法响应菜单的模板来使用,这里为了方便起见将菜单ID硬编码在程序里,你可以使用常量或资源ID来使代码更健壮。
2.使用监听器
虽然第一种方法是推荐使用的方法,android还是提供了类似java swing的监听器方式来响应菜单。使用监听器的方式分为两步:
//第一步:创建监听器类class MyMenuItemClickListener implements OnMenuItemClickListener { @Overridepublicboolean onMenuItemClick(MenuItem item) {// do something here...returntrue; //finish handling }} //第二步:为菜单项注册监听器menuItem.setOnMenuItemClickListener(new MyMenuItemClickListener());
android文档对onMenuItemClick(MenuItem item)回调方法的说明是"Called when a menu item has been invoked. This is the first code that is executed; if it returns true, no other callbacks will be executed." 可见该方法先于onOptionsItemSelected执行。
3.使用Intent响应菜单
第3种方式是直接在MenuItem上调用setIntent(Intent intent)方法,这样android会自动在该菜单被点击时调用 startActivity(Intent)
。但是个人认为与其这样还不如直接在onOptionsItemSelected的case里手动调用 startActivity(Intent)
来的直观。
Android菜单详解(三)——SubMenu和IconMenu
我们在上一篇介绍了如何在Android中创建和响应选项菜单,今天我们将探索子菜单和图标菜单。
子菜单Sub Menu
子菜单提供了一种自然的组织菜单项的方式,它被大量地运用在windows和其他OS的GUI设计中。Android同样支持子菜单,你可以通过addSubMenu(int groupId, int itemId, int order, int titleRes)方法非常方便的创建和响应子菜单。
@Overridepublicboolean onCreateOptionsMenu(Menu menu) {int base = Menu.FIRST;// 一个menu可以包括多个子菜单 SubMenu subMenu = menu.addSubMenu(base, base+1, Menu.NONE, "系统设置");// 子菜单可以包括多个菜单项 MenuItem menuitem1 = subMenu.add(base, base+1, base+1, "显示设置"); subMenu.add(base, base+2, base+2, "网络设置"); subMenu.add(base, base+3, base+3, "高级设置"); subMenu.add(base, base+4, base+4, "安全设置"); // 子菜单项不支持显示图标,这样做是没意义的,尽管不会报错! menuitem1.setIcon(R.drawable.displaysettings); //但是子菜单本身是支持图标的 subMenu.setIcon(R.drawable.settings); // 显示菜单请返回truereturntrue;}
上面的代码演示了如何创建子菜单,其菜单项的响应其实就是普通菜单项的响应,上一篇已经作了详细介绍,这里不再赘述。Android中可以为子菜单添加图标,但是不会显示其菜单项的图标,这一点需要留意。除了代码中的setIcon(int iconRes)方法,还有一个setHeaderIcon(int iconRes)方法可以添加子菜单项栏目的标题图标,效果如上面第三张图。
最后需要强调的是,Menu可以包含多个SubMenu,SubMenu可以包含多个MenuItem(这三者之间的关系见Android菜单详解(一)——理解Android中的Menu),但是SubMenu不能包含SubMenu,及子菜单不能嵌套!!!下面的代码能通过编译,但会在运行时出错。
subMenu.addSubMenu("又一个子菜单");
图标菜单Icon Menu
Android支持在菜单上显示各种各样的图标,这一点我们在上面创建子菜单时已经用到了。图标菜单严格上说并不算是一种菜单的新类型,它的使用也很简单,之所以单独设一节是为了说明使用Icon的一些限制。Android中并不是所谓的菜单项都能加上图标,以下菜单项都是不可以的(这并不意味着程序会报错,而是运行时图标得不到显示):
- 扩展的菜单项。如果不理解什么是扩展的菜单,可以参考Android菜单详解(一)——理解Android中的Menu
- 子菜单的菜单项
- 上下文菜单的菜单项
除此以外,带Icon的菜单项不能加上复选框(check mark)。总之,虽然精美的图标能给我们的应用增色不少,但是滥用图标也是会适得其反的,Android SDK给图标菜单加的这些限制也算是有效的防止我们滥用图标了吧。
结语
本篇介绍了Android中的子菜单和给菜单项加Icon时需要注意的几点,下一篇《Android菜单详解(四)——使用上下文菜单ContextMenu》将介绍上下文菜单Context Menu的使用。
之前在《Android菜单详解(二)——创建并响应选项菜单》和《Android菜单详解(三)——SubMenu和IconMenu》中详细讲解了选项菜单,子菜单和图标菜单。今天接着细说另一种被广泛使用的菜单——上下文菜单Context Menu。
ContextMenu简介
在Windows中,我们已经习惯了在文件上单击右键来执行“打开”、“重名名”、“剪切”、“删除”等操作,这个右键弹出的菜单就是上下文菜单。你可能会笑道:“哈哈,你不会连快捷键都不会用吧?”。咳咳,这个。。。举个例子嘛。没错,windows中快捷键能帮助我们提高操作的效率,但是android中这招可不管用喽,注意:android的上下文菜单项是不能用快捷键的。因为手机的操作方式与使用鼠标的PC操作方式不同,android是通过长按某个视图元素来弹出上下文菜单的(PS:现在大多数智能机是全触屏的,没有物理键盘,更没有使用快捷键的需要了,这项革新要归功于乔布斯在07发布的革命手机iPhone,老乔退休了,向他致敬!)。除此之外,甚至连图标和子菜单都无法用在Android的上下文菜单项中。那么,Android的上下文菜单到底如何使用?见下图
如图,上下文菜单继承了android.view.Menu,因此我们可以像操作Options Menu那样给上下文菜单增加菜单项。上下文菜单与Options Menu最大的不同在于,Options Menu的拥有者是Activity,而上下文菜单的拥有者是Activity中的View。每个Activity有且只有一个Options Menu,它为整个Activity服务。而一个Activity往往有多个View,并不是每个View都有上下文菜单,这就需要我们显示地通过registerForContextMenu(View view)来指定。
尽管上下文菜单的拥有者是View,生成上下文菜单却是通过Activity中的onCreateContextMenu(ContextMenu menu, View v,ContextMenu.ContextMenuInfo menuInfo)方法,该方法很像生成Options Menu的onCreateOptionsMenu(Menu menu)方法。两者的不同在于,onCreateOptionsMenu只在用户第一次按“Menu”键时被调用,而onCreateContextMenu会在用户每一次长按View时被调用,而且View必须已经注册了上下文菜单。
另一个值得注意的就是上图中的ContextMenuInfo,该类的对象被传入onCreateContextMenu(ContextMenu menu, View v,ContextMenu.ContextMenuInfo menuInfo)方法,那么它有什么用呢?有时候,视图元素需要向上下文菜单传递一些信息,比如该View对应DB记录的ID等,这就要使用ContextMenuInfo。需要传递额外信息的View需要重写getContextMenuInfo()方法,返回一个带有数据的ContextMenuInfo实现类对象。
介绍了这么多,下面给出一个demo演示如何创建和响应上下文菜单:
1.在activity的onCreate(...)方法中为一个view注册上下文菜单
2.在onCreateContextMenuInfo(...)中生成上下文菜单。
3.在onContextItemSelected(...)中响应上下文菜单项。
Demo:使用上下文菜单
1)注册上下文菜单
/** * 上下文菜单演示Demo * * @author CodingMyWorld 2011-8-27 下午03:22:39 */ publicclass SampleContextMenuActivity extends ListActivity { privatestaticfinal String TAG ="SampleContextMenuActivity"; @Override protectedvoid onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 显示列表 simpleShowList(); // 为所有列表项注册上下文菜单 this.registerForContextMenu(getListView()); } privatevoid simpleShowList() { // list item String[] files =new String[] { "文件1", "文件2", "文件3", "文件4" }; // simple array adapter ArrayAdapter<String> adapter =new ArrayAdapter<String>( this, android.R.layout.simple_list_item_1, files); // set adapter this.setListAdapter(adapter); Log.v(TAG, "show simple list"); } }
2)生成上下文菜单
在activity中重写方法。
@Override publicvoid onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { Log.v(TAG, "populate context menu"); // set context menu title menu.setHeaderTitle("文件操作"); // add context menu item menu.add(0, 1, Menu.NONE, "发送"); menu.add(0, 2, Menu.NONE, "标记为重要"); menu.add(0, 3, Menu.NONE, "重命名"); menu.add(0, 4, Menu.NONE, "删除"); }
3)响应上下文菜单项
与响应options menu类似,唯一的不同是可以通过menu info获得额外的信息。
@Override publicboolean onContextItemSelected(MenuItem item) { // 得到当前被选中的item信息 AdapterContextMenuInfo menuInfo = (AdapterContextMenuInfo) item.getMenuInfo(); Log.v(TAG, "context item seleted ID="+ menuInfo.id); switch(item.getItemId()) { case1: // do something break; case2: // do something break; case3: // do something break; case4: // do something break; default: returnsuper.onContextItemSelected(item); } returntrue; }
运行程序,多次唤出上下文菜单,注意LogCat的输出,onCreateContextMenu每一次都被调用了。
结语
至此,我们介绍完了android中的各种常用菜单,但是目前为止我们都是通过硬编码来增加菜单项的,android为此提供了一种更便利的方式,将在下一节“使用XML生成菜单”中介绍。
Android菜单详解(五)——使用XML生成菜单
回顾前面的几篇,我们都是直接在代码中添加菜单项,给菜单项分组等,这是比较传统的做法,它存在着一些不足。比如说,为了响应每个菜单项,我们需要用常量来保存每个菜单项的ID等。为此,Android提供了一种更好的方式,就是把menu也定义为应用程序的资源,通过android对资源的本地支持,使我们可以更方便地实现菜单的创建与响应。这一篇就介绍如何使用XML文件来加载和响应菜单,我们需要做这几步:
- 在/res目录下创建menu文件夹
- 在menu目录下使用与menu相关的元素定义xml文件,文件名是随意的,android会自动为其生成资源ID。例如:R.menu.mainmenu对应menu目录的mainmenu.xml资源文件
- 使用xml文件的资源ID,将xml文件中定义的菜单项添加到menu对象中
- 响应菜单项时,使用每个菜单项对应的资源ID
下面就使用xml的方式完成《Android菜单详解(二)——创建并响应选项菜单》中的options menu。
定义菜单资源文件
在res目录下创建menu文件夹,在menu下创建一个xml资源文件,我这里叫做mainmenu.xml
编写mainmenu.xml如下:
<?xml version="1.0" encoding="utf-8"?><menuxmlns:android="http://schemas.android.com/apk/res/android"><!-- group1 --><group android:id="@+id/group1"><item android:id="@+id/mi1" android:title="item1"/><item android:id="@+id/mi2" android:title="item2"/></group><!-- group 2 --><group android:id="@+id/group2"><item android:id="@+id/mi3" android:title="item3"/><item android:id="@+id/mi4" android:title="item4"/></group> </menu>
这里简单的添加了4个菜单项,并将其分为2组。item元素的android:title值可以引用values中的string资源。
使用MenuInflater添加菜单项
inflater在android中建立了从资源文件到对象的桥梁,MenuInflater即把菜单xml资源转换为对象并添加到menu对象中,它可以通过activity的getMenuInflater()得到。我们在MainActivity中重写onCreateOptionsMenu(...)方法。
@Overridepublicboolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.mainmenu, menu);returntrue;}
响应菜单项
最后重写onOptionsItemSeleted(...)方法。
@Overridepublicboolean onOptionsItemSelected(MenuItem item) {switch(item.getItemId()) {case R.id.mi1:// do sthbreak;case R.id.mi2:// do sthbreak;case R.id.mi3:// do sthbreak;case R.id.mi4:// do sthbreak; }returntrue;}
这一步最大的体现了使用XML生成菜单的好处。android不仅为我们定义的xml文件生成了资源ID,同样可以为group,menu item来自动生成ID(就像为布局中定义的view生成id那样)。这样菜单项ID的创建与管理就不用我们操心了,全部交给android去做吧!
至此,我们完成了一个简单的“使用XML生成菜单”的demo,并从中体会到了使用资源文件的好处,因此这是android中创建菜单的推荐方式。实际上,我们在代码中对菜单项或分组的操作都能在xml文件中完成,下面就简单介绍一些比较常用的功能。(谷歌提供的API demos中有最全面的示例)
更多菜单资源文件的功能
1.资源文件实现子菜单
子菜单通过在item元素中嵌套menu来实现。
<item android:title="系统设置"><menu><item android:id="@+id/mi_display_setting" android:title="显示设置"/><item android:id="@+id/mi_network_setting" android:title="网络设置"/><!-- 别的菜单项 --></menu></item>
2.为菜单项添加图标
<item android:id="@+id/mi_exit" android:title="退出" android:icon="@drawable/exit"/>
3.设置菜单项的可选出现
使用android:checkableBehavior设置一组菜单项的可选策略,可选值为:none, all, single
<group android:id="..." android:checkableBehavior="all"><!-- 菜单项 --></group>
使用android:checked设置特定菜单项
<item android:id="..." android:title="sometitle" android:checked="true"/>
4.设置菜单项可用/不可用
<item android:id="..." android:title="sometitle" android:enabled="false"/>
5.设置菜单项可见/不可见
<item android:id="..." android:title="sometitle" android:visible="false"/>
结语
本篇是Android菜单详解系列的最后一篇,本系列详细介绍了android中各种常用菜单的使用技巧和注意事项,希望能帮助大家更好的理解,也期待与各位交流开发中的心得:)
转载于:https://www.cnblogs.com/Tammie/archive/2012/08/24/2653728.html
Android菜单详解——理解android中的Menu相关推荐
- 【转】Android菜单详解——理解android中的Menu--不错
原文网址:http://www.cnblogs.com/qingblog/archive/2012/06/08/2541709.html 前言 今天看了pro android 3中menu这一章,对A ...
- Android菜单详解(三)——SubMenu和IconMenu
我们在上一篇介绍了如何在Android中创建和响应选项菜单,今天我们将探索子菜单和图标菜单. 子菜单Sub Menu 子菜单提供了一种自然的组织菜单项的方式,它被大量地运用在windows和其他OS的 ...
- android子视图无菜单,Android 菜单详解
Android中菜单分为三种,选项菜单(OptionMenu),上下文菜单(ContextMenu),子菜单(SubMenu) 选项菜单 可以通过两种办法增加选项菜单,一是在menu.xml中添加,该 ...
- android菜单详解三:上下文菜单
创建一个上下文菜单 一个上下文菜单跟PC上的右键菜单类似.你应使用上下文菜单为用户界面上的某个部分提供动作选择功能.在Android中,一个上下文菜单会在用户长按一个界面条目时出现. 你可以为任何Vi ...
- android开发菜单,Android学习指南之十六:Android菜单详解
Android用户界面的组成除了View外,还包括菜单和对话框,本节我们先来学习一下菜单的使用方法. 菜单Menu是Android用户界面中最常见的元素之一,使用非常频繁.Android菜单主要分为三 ...
- android菜单详解二:选项菜单
创建一个选项菜单 选项菜单里应该包含基本的activity动作和必须的导航条目 (例如,一个打开程序设置的菜单项). 选项菜单的菜单项有两种不同的选择方法,一是菜单项按钮,二是通过 Action Ba ...
- android菜单详解四:子菜单
创建子菜单们 一个子菜单是一个在已有菜单的某个菜单项上打开的菜单.你可以向任何菜单添加子菜单.当你的程序拥有很多功能并可按类别组织起来,那么子菜单是最佳选择.比如PC 程序中的菜单栏 (File, E ...
- Android菜单详解——子菜单(SubMenu)
1,子菜单就是将功能相同或相似的分组进行多级显示的一种菜单. 2,创建子菜单的步骤: a) 覆盖Activity的onCreateOptionsMenu()方法,调用Menu的addSubMenu() ...
- Android动画详解之Android 动画属性和实现方法之帧动画(二)
一.简介 Frame Animation(AnimationDrawable对象):帧动画,就像GIF图片,通过一系列Drawable依次显示来模拟动画的效果. 必须以<animation-li ...
最新文章
- 安全证书导入到java中的cacerts证书库
- Android在桌面上添加开关,多键开关 Andromax v1.1.7
- 网络推广公司介绍几个能提升网站收录的“隐藏版”小技巧!
- [名词解释] intuitive
- 解构电商产品——订单系统(一)
- 作业帮电脑版在线使用_在线K12赛道六虎争霸:猿辅导、作业帮又宣布新一轮融资...
- SigmaStar SSD201 操作记录
- 性能优化之图片懒加载
- dockerq启动报错(iptables failed: iptables --wait -t nat -A DOCKER -p tcp -d 0/0 --dport 9876 -j DNAT --t
- 记录一次webpack3升级到webpack4过程
- JQuery Datatables editor进行增删改查操作(二)
- Windows编程—获取操作系统默认浏览器路径
- Android关闭Activity
- springmvc 静态资源 配置
- 聚类算法-密度聚类算法DBSCAN
- 秒懂VRRP协议原理及配置
- 【diannaoxitong】word安全模式怎么解除?word安全模式快速解除方法
- arm的一些概念(ARM9、Cortex的区别)
- css轻松写出梦幻西游动画效果
- 物联网大赛 - Android学习笔记(三)Android 事件处理
热门文章
- python官方网站地址-index
- python数字类型-Python基础:数据类型-数字(5)
- python容易学吗-python容易学么
- 学会python爬虫怎么赚钱-学会Python爬虫能赚大钱吗?Python爬虫赚钱渠道分享
- 学python要多少钱-python学习费用多少合适
- 普通人学python有用吗-普通人为什么要学习Python?
- python可以从事什么工作-学Python能干什么工作?工作前景怎么样?
- python3.5怎么使用-Python3.5常见内置方法参数用法实例详解
- 大学计算机基础课程报告python-大学计算机基础
- python学习手册中文版免费下载-Python学习手册 第三版