前言

  本篇博客讲解一下菜单Menu的使用。菜单在windows应用中使用十分广泛,几乎所有的windows应用都有菜单,Android中也加入了菜单的支持。从官方文档了解到,从Android3.0(API level 11)开始,Android设备不再要求提供一个专门的菜单按钮,转而推荐使用ActionBar。所以现在市面上很多新设备使用三个虚拟按键,并不再额外提供菜单按钮,但是按钮的使用也是有些地方可以借鉴的。

  因为Android版本的发展,对于菜单的支持各个版本有很大的区别,而Android3.0是个分水岭,大概可以分为下面三类:

  • OptionMenu和ActionBar:一些操作的集合,如果开发的平台在Android3.0之上,推荐使用ActionBar,如果开发的平台在Android2.3或之下,还是可以使用OptionMenu的。
  • ContextMenu和ActionMode:ContextMenu是一个浮动的窗口形式展现一个选项列表,ActionMode是一个显示在屏幕顶部的操作栏,允许用户选择多个选项,ActionMode在Android3.0之后才有支持。
  • Pupop Menu:PopupMenu是固定在View上的模态菜单,以弹出的方式显示,在Android3.0之后才有支持。

  

在XML中定义一个菜单

  Android提供了标准的XML格式的资源文件来定义菜单项,并且对所有菜单类型都支持,推荐使用XML资源文件来定义菜单,之后再把它Inflater到Activity或者Fragment中,而不是在Activity中使用代码声明。

  而菜单的XML资源文件,需要创建在/res/menu/目录下,并且包含一下几个元素:

  • <menu>:定义一个Menu,是一个菜单资源文件的根节点,里面可以包含一个或者多个<item>和<group>元素。
  • <item>:创建一个MenuItem,代表了菜单中一个选项。
  • <group>:对菜单项进行分组,可以以组的形式操作菜单项。

  <item>元素除了常规的id、icon、title属性的支持,还有一个重要的属性:android:showAsAction,这个属性是起兼容性的,描述了在Android的高版本中,菜单项何时以何种方式加入到ActionBar中。

  <group>是对菜单进行分组,分组后的菜单显示效果并没有区别,唯一的区别在于可以针对菜单组进行操作,这样对于分类的菜单项,操作起来更方便,提供如下的操作:

  • Menu.setGroupCheckable():菜单组内的菜单是否都可选。
  • Menu.setGroupVisible():是否隐藏菜单组的所有菜单。
  • Menu.setGroupEnabled():菜单组的菜单是否有用。

  如果菜单项需要单选或者多选,可以使用android:checkableBehavior属性设置,它可以对单个<item>或者<group>设置一个组,这个属性接受三个参数:single,单选;all,多选,none,没有Checked的选项,默认。

  当创建好一个XML菜单资源文件之后,可以使用MenuInflater.inflate()方法填充菜单资源,使XML资源变成一个可编程的对象。

OptionMenu

  OptionMenu,选项菜单,必须设备具有菜单按钮才可以触发。因为屏幕的限制,最多只能展示六个菜单项,如果定义的菜单项超出了六个,其他的菜单项将被隐藏,第六个菜单将会显示“更多”,点击展开更多的菜单。虽说在Android3.0之后不再推荐使用选项菜单,但是如果使用了,在Android3.0之后的设备上,选项菜单项将被默认转移到ActionBar中,这个可以通过android:showAsAction属性控制。

  使用OptionMenu需要在Activity或者Fragment中重写onCreateOptionsMenu(Menu)方法,在这个方法中声明一个选项菜单。菜单的存在是为了提供操作,所以Activity和Fragment中还提供了一个onOptionsItemSelected(MenuItem)方法,用于响应选项菜单中选中的时候的响应。OptionMenu就是操作一个Menu对象和MenuItem对象。

  下面通过两个Demo来展示一段选项菜单的使用,分别使用代码声明菜单和XML资源文件声明菜单的方式说明。

  声明代码:

 1 package com.example.menudemo;
 2
 3 import android.app.Activity;
 4 import android.content.Intent;
 5 import android.os.Bundle;
 6 import android.view.Menu;
 7 import android.view.MenuItem;
 8 import android.view.SubMenu;
 9 import android.widget.Toast;
10
11 public class OptionMenu1Activitty extends Activity {
12
13     @Override
14     protected void onCreate(Bundle savedInstanceState) {
15         // TODO Auto-generated method stub
16         super.onCreate(savedInstanceState);
17         setContentView(R.layout.activity_optionmenu1);
18     }
19
20     @Override
21     public boolean onCreateOptionsMenu(Menu menu) {
22
23         //直接Add菜单选项到Menu中
24         menu.add(1000, 100, 0, "System menu");
25         //获取添加的菜单选项,然后设置其图标
26         MenuItem menuItem2=menu.add(1000, 101, 1, "User menu");
27         menuItem2.setIcon(R.drawable.ic_launcher);
28         //获取添加的菜单选项,增加一个Intent,点击后转向IntentActivity
29         MenuItem menuItem3=menu.add(1000, 102, 2, "Intent menu");
30         menuItem3.setIcon(R.drawable.ic_launcher);
31         Intent intent=new Intent(OptionMenu1Activitty.this, IntentActivity.class);
32         menuItem3.setIntent(intent);
33
34         //添加一个SubMenu,点击后弹出一个子菜单对话框
35         SubMenu submenu=menu.addSubMenu(1000, 103, 3, "Sub menus");
36         submenu.add(1000, 104, 4, "Sub ment1");
37         submenu.add(1000, 105, 4, "Sub ment2");
38         submenu.add(1000, 106, 4, "Sub ment3");
39         return true;
40     }
41
42     @Override
43     public boolean onOptionsItemSelected(MenuItem item) {
44         boolean flag;
45         switch (item.getItemId()) {
46         case 100:
47             Toast.makeText(OptionMenu1Activitty.this, "selected System menu", Toast.LENGTH_SHORT).show();
48             flag=true;
49             break;
50         case 101:
51             Toast.makeText(OptionMenu1Activitty.this, "selected User menu", Toast.LENGTH_SHORT).show();
52             flag=true;
53             break;
54         case 104:
55             Toast.makeText(OptionMenu1Activitty.this, "selected Sub menu1", Toast.LENGTH_SHORT).show();
56             flag=true;
57         default:
58             flag=super.onOptionsItemSelected(item);
59             break;
60         }
61         return flag;
62     }
63
64 }

  实现效果,Android2.3:

  使用XML资源文件定义选项菜单,XML资源文件:

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <menu xmlns:android="http://schemas.android.com/apk/res/android" >
 3
 4     <item
 5         android:id="@+id/item1"
 6         android:showAsAction="never"
 7         android:title="System menu">
 8     </item>
 9     <item
10         android:id="@+id/item2"
11         android:showAsAction="never"
12         android:title="User menu"
13         android:icon="@drawable/ic_launcher">
14     </item>
15     <item
16         android:id="@+id/item3"
17         android:showAsAction="never"
18         android:title="Intent menu"
19         android:icon="@drawable/ic_launcher">
20     </item>
21     <group android:id="@+id/group_file" >
22         <item android:id="@+id/menu_save"
23               android:title="menu group save" />
24         <item android:id="@+id/menu_delete"
25               android:title="menu group delete" />
26     </group>
27     <item android:id="@+id/file"
28           android:title="Sub menus" >
29         <!-- "file" submenu -->
30         <menu>
31             <item android:id="@+id/sub_menu1"
32                   android:title="Sub menu1" />
33             <item android:id="@+id/sub_menu21"
34                   android:title="Sub menu2" />
35             <item android:id="@+id/sub_menu3"
36                   android:title="Sub menu3" />
37         </menu>
38     </item>
39 </menu>

 Java代码:

 1 package com.example.menudemo;
 2
 3 import android.app.Activity;
 4 import android.content.Intent;
 5 import android.os.Bundle;
 6 import android.view.Menu;
 7 import android.view.MenuItem;
 8 import android.widget.TextView;
 9 import android.widget.Toast;
10
11 public class OptionMenu2Activitty extends Activity {
12     private TextView  tv;
13     @Override
14     protected void onCreate(Bundle savedInstanceState) {
15         // TODO Auto-generated method stub
16         super.onCreate(savedInstanceState);
17         setContentView(R.layout.activity_optionmenu1);
18         tv=(TextView)findViewById(R.id.tvOptionMenu1);
19         tv.setText("加载XML资源填充Menu");
20     }
21
22     @Override
23     public boolean onCreateOptionsMenu(Menu menu) {
24         // 使用布局文件加载菜单
25         getMenuInflater().inflate(R.menu.optionmenu2, menu);
26         return super.onCreateOptionsMenu(menu);
27     }
28
29     @Override
30     public boolean onOptionsItemSelected(MenuItem item) {
31
32         switch (item.getItemId()) {
33         case R.id.item1:
34             Toast.makeText(OptionMenu2Activitty.this, "selected System menu", Toast.LENGTH_SHORT).show();
35             return true;
36         case R.id.item2:
37             Toast.makeText(OptionMenu2Activitty.this, "selected User menu", Toast.LENGTH_SHORT).show();
38             return true;
39         case R.id.item3:
40             Intent intent=new Intent(OptionMenu2Activitty.this, IntentActivity.class);
41             startActivity(intent);
42             return true;
43         case R.id.menu_save:
44             Toast.makeText(OptionMenu2Activitty.this, "file save", Toast.LENGTH_SHORT).show();
45             return true;
46         case R.id.sub_menu1:
47             Toast.makeText(OptionMenu2Activitty.this, "Selected sub_menu1", Toast.LENGTH_SHORT).show();
48             return true;
49         default:
50             return super.onOptionsItemSelected(item);
51         }
52
53
54     }
55
56 }

  效果和使用Java代码声明菜单一样,这里就不再展示了。

ContextMenu

  ContextMenu,上下文菜单提供了注册在View组件的菜单操作,它以一个浮动的窗口显示(类似于对话框),当用户长按某被注册了上下文菜单的视图,则触发上下文菜单显示。通常都用于ListView或者GridView等视图集合中。

  使用上下文菜单的步骤:

  1. 使用Activity.registerForContextMenu(View)方法为指定View注册上下文菜单。
  2. 在Activity或者Fragment中重写onCreateContextMenu()方法,当被注册的视图接受到长按事件后,系统调用onCreateContextMenu()方法,在这个方法中声明上下文菜单。
  3. 实现onContextItemSelected()方法,用于响应菜单想的选中。

  示例,菜单XML资源文件代码:

 1 <menu xmlns:android="http://schemas.android.com/apk/res/android" >
 2
 3      <item
 4         android:id="@+id/context_copy"
 5         android:orderInCategory="100"
 6         android:showAsAction="never"
 7         android:title="Copy"/>
 8     <item
 9         android:id="@+id/context_edit"
10         android:orderInCategory="100"
11         android:showAsAction="never"
12         android:title="Edit"/>
13     <item
14         android:id="@+id/context_delete"
15         android:orderInCategory="100"
16         android:showAsAction="never"
17         android:title="Delete"/>
18 </menu>

  Java代码:

 1 package com.example.menudemo;
 2
 3 import java.util.ArrayList;
 4 import java.util.List;
 5
 6 import android.app.Activity;
 7 import android.os.Bundle;
 8 import android.view.ContextMenu;
 9 import android.view.MenuInflater;
10 import android.view.MenuItem;
11 import android.view.View;
12 import android.view.ContextMenu.ContextMenuInfo;
13 import android.widget.AdapterView.AdapterContextMenuInfo;
14 import android.widget.ArrayAdapter;
15 import android.widget.ListView;
16 import android.widget.Toast;
17
18 public class ContextMenu1 extends Activity {
19     private ListView listview;
20     private List<String> dataList;
21     @Override
22     protected void onCreate(Bundle savedInstanceState) {
23         super.onCreate(savedInstanceState);
24         setContentView(R.layout.activity_contextmenu1);
25         listview=(ListView)findViewById(R.id.listView1);
26         dataList=getData();
27         ArrayAdapter<String> adapter=new  ArrayAdapter<String>(ContextMenu1.this,android.R.layout.simple_list_item_1, dataList);
28         listview.setAdapter(adapter);
29         //为ListView注册上下文菜单
30         registerForContextMenu(listview);
31     }
32
33     @Override
34     public void onCreateContextMenu(ContextMenu menu, View v,
35             ContextMenuInfo menuInfo) {
36         super.onCreateContextMenu(menu, v, menuInfo);
37         //填充一个XML菜单文件
38         MenuInflater inflater = getMenuInflater();
39         inflater.inflate(R.menu.contextmenu, menu);
40     }
41
42     @Override
43     public boolean onContextItemSelected(MenuItem item) {
44         //获取上下文菜单绑定的AdapterView的额外信息
45         AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
46         switch (item.getItemId()) {
47         case R.id.context_copy:
48             Toast.makeText(ContextMenu1.this, "copy "+dataList.get(info.position), Toast.LENGTH_SHORT).show();
49             return true;
50         case R.id.context_delete:
51             Toast.makeText(ContextMenu1.this, "delete "+dataList.get(info.position), Toast.LENGTH_SHORT).show();
52             return true;
53         case R.id.context_edit:
54             Toast.makeText(ContextMenu1.this, "edit " +dataList.get(info.position), Toast.LENGTH_SHORT).show();
55             return true;
56         default:
57             return super.onContextItemSelected(item);
58         }
59     }
60     //ListView数据
61     public List<String> getData()
62     {
63         List<String> data=new ArrayList<String>();
64         for(int i=0;i<8;i++)
65         {
66             data.add("item"+i);
67         }
68         return data;
69     }
70 }

  效果展示,Android4.0:

ActionMode

  ActionMode,是一个系统实现的用户交互,当用户使用ActionMode后,选择一个选项,一个上下文操作栏会出现在屏幕的顶端,呈现出用户可以对当前选中项目进行的操作选项。进入这种状态可以通过后退按钮或者调用finish()退出。ActionMode为Android3.0之后的支持,所以在开发3.0之后的应用,推荐使用ActionMode,而不是ContextMenu。

  使用ActionMode的步骤:

  1. 实现ActionMode.Callback接口。在它的回调方法中,可以设置操作的上下文操作栏。
  2. 在需要显示上下文操作栏的时候,调用startActionMode(ActionMode.Callback)。

  ActionMode.Callback是ActionMode定义的一个内部接口,这个接口需要实现下面四个方法:

  • boolean onCreateActionMode(ActionMode mode,Menu menu):第一次被创建的时候调用。
  • boolean onPrepareActionMode(ActionMode mode,Menu menu):刷新菜单列表的时候被调用,一般使用false即可。
  • boolean onActionItemClicked(ActionMode mode,MenuItem item):菜单项被选中的时候被调用。
  • void onDestroyActionMode(ActionMode mode):退出或销毁的时候被调用。

  示例:

  1 package com.example.menudemo;
  2
  3 import java.util.ArrayList;
  4 import java.util.List;
  5
  6 import android.annotation.SuppressLint;
  7 import android.app.Activity;
  8 import android.os.Bundle;
  9 import android.view.ActionMode;
 10 import android.view.ActionMode.Callback;
 11 import android.view.Menu;
 12 import android.view.MenuInflater;
 13 import android.view.MenuItem;
 14 import android.view.View;
 15 import android.widget.AdapterView;
 16 import android.widget.AdapterView.AdapterContextMenuInfo;
 17 import android.widget.AdapterView.OnItemLongClickListener;
 18 import android.widget.ArrayAdapter;
 19 import android.widget.ListView;
 20 import android.widget.Toast;
 21
 22 public class ActionModeMenu1 extends Activity {
 23     private ListView listview;
 24     private List<String> dataList;
 25     private ActionMode mActionMode;
 26     @Override
 27     protected void onCreate(Bundle savedInstanceState) {
 28         // TODO Auto-generated method stub
 29         super.onCreate(savedInstanceState);
 30         setContentView(R.layout.activity_contextmenu1);
 31         listview=(ListView)findViewById(R.id.listView1);
 32         dataList=getData();
 33         ArrayAdapter<String> adapter=new  ArrayAdapter<String>(ActionModeMenu1.this,android.R.layout.simple_list_item_1, dataList);
 34         listview.setAdapter(adapter);
 35         listview.setOnItemLongClickListener(new OnItemLongClickListener() {
 36             @SuppressLint("NewApi")
 37             @Override
 38             public boolean onItemLongClick(AdapterView<?> parent, View view,
 39                     int position, long id) {
 40                 if (mActionMode != null) {
 41                     return false;
 42                 }
 43                 //显示ActionMode
 44                 mActionMode = startActionMode(mActionModeCallback);
 45                 //标记选中项的下表
 46                 mActionMode.setTag(position);
 47                 //标记ListView为可选状态
 48                 view.setSelected(true);
 49                 return true;
 50             }
 51         });
 52     }
 53     public List<String> getData()
 54     {
 55         List<String> data=new ArrayList<String>();
 56         for(int i=0;i<8;i++)
 57         {
 58             data.add("item"+i);
 59         }
 60         return data;
 61     }
 62
 63     private ActionMode.Callback mActionModeCallback=new Callback() {
 64
 65         @Override
 66         public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
 67             //刷新菜单列表的时候被调用,但是一般无需刷新
 68             return false;
 69         }
 70
 71         @Override
 72         public void onDestroyActionMode(ActionMode mode) {
 73             //销毁ActionMode
 74             mActionMode = null;
 75         }
 76
 77         @Override
 78         public boolean onCreateActionMode(ActionMode mode, Menu menu) {
 79             //创建ActionMode
 80             //使用资源文件填充
 81             MenuInflater inflater = mode.getMenuInflater();
 82             inflater.inflate(R.menu.contextmenu, menu);
 83             return true;
 84         }
 85
 86         @Override
 87         public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
 88             //获取选项中下表
 89             int position=(Integer)mode.getTag();
 90             switch (item.getItemId()) {
 91             case R.id.context_copy:
 92                 Toast.makeText(ActionModeMenu1.this, "copy "+dataList.get(position), Toast.LENGTH_SHORT).show();
 93                 //finish退出ActionMode模式
 94                 mode.finish();
 95                 return true;
 96             case R.id.context_delete:
 97                 Toast.makeText(ActionModeMenu1.this, "delete "+dataList.get(position), Toast.LENGTH_SHORT).show();
 98                 mode.finish();
 99                 return true;
100             case R.id.context_edit:
101                 Toast.makeText(ActionModeMenu1.this, "edit " +dataList.get(position), Toast.LENGTH_SHORT).show();
102                 mode.finish();
103                 return true;
104             default:
105                 return false;
106         }
107         }
108     };
109
110
111 }

 效果展示,Android4.0:

 

PopupMenu

  PopupMenu,弹出菜单,一个模态形式展示的弹出风格的菜单,绑在在某个View上,一般出现在被绑定的View的下方(如果下方有空间)。

  使用PopupMenu的步骤:

  1. 通过PopupMenu的构造函数实例化一个PopupMenu对象,需要传递一个当前上下文对象以及绑定的View。
  2. 调用PopupMenu.setOnMenuItemClickListener()设置一个PopupMenu选项的选中事件。
  3. 使用MenuInflater.inflate()方法加载一个XML文件到PopupMenu.getMenu()中。
  4. 在需要的时候调用PopupMenu.show()方法显示。

  示例:

 1     public void showPopup(View v){
 2         PopupMenu popup=new PopupMenu(MainActivity.this, v);
 3         popup.setOnMenuItemClickListener(new OnMenuItemClickListener() {
 4
 5             @Override
 6             public boolean onMenuItemClick(MenuItem item) {
 7                 switch (item.getItemId()) {
 8                 case R.id.context_copy:
 9                     Toast.makeText(MainActivity.this, "select copy ", Toast.LENGTH_SHORT).show();
10                     return true;
11                 case R.id.context_delete:
12                     Toast.makeText(MainActivity.this, " select delete ", Toast.LENGTH_SHORT).show();
13                     return true;
14                 case R.id.context_edit:
15                     Toast.makeText(MainActivity.this, " select edit ", Toast.LENGTH_SHORT).show();
16                     return true;
17                     default :
18                     return false;
19                 }
20             }
21         });
22         popup.getMenuInflater().inflate(R.menu.contextmenu,popup.getMenu());
23         popup.show();
24     }

  效果展示,Android4.0:

  源码下载

总结

  以上就讲解了Android下Menu的使用。因为上面的所有示例均在一个项目中完成的,所以有些低版本的操作,需要更改AndroidManifest.xml文件中的最低支持版本,改到8即可。在现在的实际开发中,最好还是使用对高版本只是的ActionBar、ActionMode、PopupMenu比较好。

Android--Menus相关推荐

  1. android每日一问【2011-8-26】

    Android布局属性详解 listview多选的一个问题 关于动画参数设置的问题,在线等,谢谢啦. 对话框简单应用 listview下面显示一些东西.代码写上去.可是运行起来看不到 搭建Androi ...

  2. 使用Kotlin的Android菜单

    In this tutorial, we'll be discussing and implement the Android Menu class in our android applicatio ...

  3. ios vs android设计

    重点 (Top highlight) This article has been written by Artur Abrarov from Redmadrobot. Translated and r ...

  4. android菜单_Android菜单简介

    android菜单 There are three types of menus in Android: Popup, Contextual and Options. Android中有三种类型的菜单 ...

  5. Android Contextual Menus之二:contextual action mode

    Android Contextual Menus之二:contextual action mode 接上文:Android Contextual Menus之一:floating context me ...

  6. 构建node.js基础镜像_在Android上构建Node.js应用程序

    构建node.js基础镜像 by Aurélien Giraud 通过AurélienGiraud 在Android上构建Node.js应用程序-第1部分:Termux,Vim和Node.js (Bu ...

  7. Android学习笔记--处理UI事件

    Handling UI Events 在Android里, 有不只一种方式可以截获用户与你的应用程序交互的事件. 在你的界面上处理事件时,你需要捕获用户与某个View实例交互时所产生的事件.View类 ...

  8. Android实现导航菜单左右滑动效果

    本文给大家介绍在Android中如何实现顶部导航菜单左右滑动效果. 今天给大家介绍在Android中实现顶部导航菜单左右滑动效果的二种解决方案. 第一种解决方案:  在以前的一篇博文中我使用andro ...

  9. Android Jetpack组件之Navigation使用-源码

    1.前言 最近简单看了下google推出的框架Jetpack,感觉此框架的内容可以对平时的开发有很大的帮助,也可以解决很多开发中的问题,对代码的逻辑和UI界面实现深层解耦,打造数据驱动型UI界面. A ...

  10. Android 开源项目集合

    2019独角兽企业重金招聘Python工程师标准>>> 上百个Android开源项目分享,希望对android开发有帮助. Android PDF 阅读器 http://source ...

最新文章

  1. python for 循环 多线程_python:for循环中的多线程处理
  2. hdoj-2039-三角形
  3. 洛谷P1162 填涂颜色
  4. 什么是latex科技排版系统,有对比word有何不同?
  5. winform中openfiledialog过滤压缩文件格式_5种最佳摄影师图像文件格式
  6. 深度学习——第二次浪潮、寒冬与解冻
  7. struts工作原理(图解)
  8. 微服务SpringCloud之Feign简介及使用
  9. 教你用 Android 做二次开发,识别率达到科大讯飞语音输入水平 | 原力计划
  10. [UOJ386]鸽子固定器
  11. python time、datetime模块学习使用
  12. 基于SSM的NBA篮球球队运营系统
  13. ES(二)| 安装ES、Kibana、IK分词器、拼音分词器(自动补全)
  14. Linux编程基础之Makefile的使用
  15. RFT API初涉——之解决RFT无法识别windows对话框的问题
  16. 双光耦开关电源电路图_开关电源中的光耦典型电路设计分析
  17. SwiftUI实战教程 第二章 BMI计算器
  18. Adobe 2021正式版发布!全新的adobe2021和2020有哪些区别?
  19. hihocoder图像算子(高斯消元)
  20. 森林的先序和中序遍历

热门文章

  1. matlab出图时汉字都变成方框_linux下Matlab 2020中文字体方框问题解决方法
  2. HashMap、LinkedHashMap、HashTable、HashSet笔记
  3. APMServ5.2.6win10系统Apache、MySQL5.1启动失败解决办法
  4. 自定义Toast的出现样式
  5. 为什么现代企业需提高企业敏捷性
  6. 使用pumysql 查询数据插入另外一张表
  7. 网易新闻iOS版开发使用的第三方框架和组件列表
  8. 在Flex4中嵌入字体
  9. yourphp添加KindEditor编辑器
  10. 为suse 12.3桌面系统安装金山WPS OFFICE