前言

  本篇博客讲解一下菜单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资源文件声明菜单的方式说明。

  声明代码:

 package com.example.menudemo;

 import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SubMenu;
import android.widget.Toast; public class OptionMenu1Activitty extends Activity { @Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_optionmenu1);
} @Override
public boolean onCreateOptionsMenu(Menu menu) { //直接Add菜单选项到Menu中
menu.add(1000, 100, 0, "System menu");
//获取添加的菜单选项,然后设置其图标
MenuItem menuItem2=menu.add(1000, 101, 1, "User menu");
menuItem2.setIcon(R.drawable.ic_launcher);
//获取添加的菜单选项,增加一个Intent,点击后转向IntentActivity
MenuItem menuItem3=menu.add(1000, 102, 2, "Intent menu");
menuItem3.setIcon(R.drawable.ic_launcher);
Intent intent=new Intent(OptionMenu1Activitty.this, IntentActivity.class);
menuItem3.setIntent(intent); //添加一个SubMenu,点击后弹出一个子菜单对话框
SubMenu submenu=menu.addSubMenu(1000, 103, 3, "Sub menus");
submenu.add(1000, 104, 4, "Sub ment1");
submenu.add(1000, 105, 4, "Sub ment2");
submenu.add(1000, 106, 4, "Sub ment3");
return true;
} @Override
public boolean onOptionsItemSelected(MenuItem item) {
boolean flag;
switch (item.getItemId()) {
case 100:
Toast.makeText(OptionMenu1Activitty.this, "selected System menu", Toast.LENGTH_SHORT).show();
flag=true;
break;
case 101:
Toast.makeText(OptionMenu1Activitty.this, "selected User menu", Toast.LENGTH_SHORT).show();
flag=true;
break;
case 104:
Toast.makeText(OptionMenu1Activitty.this, "selected Sub menu1", Toast.LENGTH_SHORT).show();
flag=true;
default:
flag=super.onOptionsItemSelected(item);
break;
}
return flag;
} }

  实现效果,Android2.3:

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

 <?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" > <item
android:id="@+id/item1"
android:showAsAction="never"
android:title="System menu">
</item>
<item
android:id="@+id/item2"
android:showAsAction="never"
android:title="User menu"
android:icon="@drawable/ic_launcher">
</item>
<item
android:id="@+id/item3"
android:showAsAction="never"
android:title="Intent menu"
android:icon="@drawable/ic_launcher">
</item>
<group android:id="@+id/group_file" >
<item android:id="@+id/menu_save"
android:title="menu group save" />
<item android:id="@+id/menu_delete"
android:title="menu group delete" />
</group>
<item android:id="@+id/file"
android:title="Sub menus" >
<!-- "file" submenu -->
<menu>
<item android:id="@+id/sub_menu1"
android:title="Sub menu1" />
<item android:id="@+id/sub_menu21"
android:title="Sub menu2" />
<item android:id="@+id/sub_menu3"
android:title="Sub menu3" />
</menu>
</item>
</menu>

 Java代码:

 package com.example.menudemo;

 import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;
import android.widget.Toast; public class OptionMenu2Activitty extends Activity {
private TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_optionmenu1);
tv=(TextView)findViewById(R.id.tvOptionMenu1);
tv.setText("加载XML资源填充Menu");
} @Override
public boolean onCreateOptionsMenu(Menu menu) {
// 使用布局文件加载菜单
getMenuInflater().inflate(R.menu.optionmenu2, menu);
return super.onCreateOptionsMenu(menu);
} @Override
public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) {
case R.id.item1:
Toast.makeText(OptionMenu2Activitty.this, "selected System menu", Toast.LENGTH_SHORT).show();
return true;
case R.id.item2:
Toast.makeText(OptionMenu2Activitty.this, "selected User menu", Toast.LENGTH_SHORT).show();
return true;
case R.id.item3:
Intent intent=new Intent(OptionMenu2Activitty.this, IntentActivity.class);
startActivity(intent);
return true;
case R.id.menu_save:
Toast.makeText(OptionMenu2Activitty.this, "file save", Toast.LENGTH_SHORT).show();
return true;
case R.id.sub_menu1:
Toast.makeText(OptionMenu2Activitty.this, "Selected sub_menu1", Toast.LENGTH_SHORT).show();
return true;
default:
return super.onOptionsItemSelected(item);
} } }

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

ContextMenu

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

  使用上下文菜单的步骤:

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

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

 <menu xmlns:android="http://schemas.android.com/apk/res/android" >

      <item
android:id="@+id/context_copy"
android:orderInCategory="100"
android:showAsAction="never"
android:title="Copy"/>
<item
android:id="@+id/context_edit"
android:orderInCategory="100"
android:showAsAction="never"
android:title="Edit"/>
<item
android:id="@+id/context_delete"
android:orderInCategory="100"
android:showAsAction="never"
android:title="Delete"/>
</menu>

  Java代码:

 package com.example.menudemo;

 import java.util.ArrayList;
import java.util.List; import android.app.Activity;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ContextMenu.ContextMenuInfo;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast; public class ContextMenu1 extends Activity {
private ListView listview;
private List<String> dataList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_contextmenu1);
listview=(ListView)findViewById(R.id.listView1);
dataList=getData();
ArrayAdapter<String> adapter=new ArrayAdapter<String>(ContextMenu1.this,android.R.layout.simple_list_item_1, dataList);
listview.setAdapter(adapter);
//为ListView注册上下文菜单
registerForContextMenu(listview);
} @Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
//填充一个XML菜单文件
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.contextmenu, menu);
} @Override
public boolean onContextItemSelected(MenuItem item) {
//获取上下文菜单绑定的AdapterView的额外信息
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
switch (item.getItemId()) {
case R.id.context_copy:
Toast.makeText(ContextMenu1.this, "copy "+dataList.get(info.position), Toast.LENGTH_SHORT).show();
return true;
case R.id.context_delete:
Toast.makeText(ContextMenu1.this, "delete "+dataList.get(info.position), Toast.LENGTH_SHORT).show();
return true;
case R.id.context_edit:
Toast.makeText(ContextMenu1.this, "edit " +dataList.get(info.position), Toast.LENGTH_SHORT).show();
return true;
default:
return super.onContextItemSelected(item);
}
}
//ListView数据
public List<String> getData()
{
List<String> data=new ArrayList<String>();
for(int i=0;i<8;i++)
{
data.add("item"+i);
}
return data;
}
}

  效果展示,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):退出或销毁的时候被调用。

  示例:

 package com.example.menudemo;

 import java.util.ArrayList;
import java.util.List; import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.view.ActionMode;
import android.view.ActionMode.Callback;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast; public class ActionModeMenu1 extends Activity {
private ListView listview;
private List<String> dataList;
private ActionMode mActionMode;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_contextmenu1);
listview=(ListView)findViewById(R.id.listView1);
dataList=getData();
ArrayAdapter<String> adapter=new ArrayAdapter<String>(ActionModeMenu1.this,android.R.layout.simple_list_item_1, dataList);
listview.setAdapter(adapter);
listview.setOnItemLongClickListener(new OnItemLongClickListener() {
@SuppressLint("NewApi")
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view,
int position, long id) {
if (mActionMode != null) {
return false;
}
//显示ActionMode
mActionMode = startActionMode(mActionModeCallback);
//标记选中项的下表
mActionMode.setTag(position);
//标记ListView为可选状态
view.setSelected(true);
return true;
}
});
}
public List<String> getData()
{
List<String> data=new ArrayList<String>();
for(int i=0;i<8;i++)
{
data.add("item"+i);
}
return data;
} private ActionMode.Callback mActionModeCallback=new Callback() { @Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
//刷新菜单列表的时候被调用,但是一般无需刷新
return false;
} @Override
public void onDestroyActionMode(ActionMode mode) {
//销毁ActionMode
mActionMode = null;
} @Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
//创建ActionMode
//使用资源文件填充
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.contextmenu, menu);
return true;
} @Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
//获取选项中下表
int position=(Integer)mode.getTag();
switch (item.getItemId()) {
case R.id.context_copy:
Toast.makeText(ActionModeMenu1.this, "copy "+dataList.get(position), Toast.LENGTH_SHORT).show();
//finish退出ActionMode模式
mode.finish();
return true;
case R.id.context_delete:
Toast.makeText(ActionModeMenu1.this, "delete "+dataList.get(position), Toast.LENGTH_SHORT).show();
mode.finish();
return true;
case R.id.context_edit:
Toast.makeText(ActionModeMenu1.this, "edit " +dataList.get(position), Toast.LENGTH_SHORT).show();
mode.finish();
return true;
default:
return false;
}
}
}; }

 效果展示,Android4.0:

 

PopupMenu

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

  使用PopupMenu的步骤:

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

  示例:

     public void showPopup(View v){
PopupMenu popup=new PopupMenu(MainActivity.this, v);
popup.setOnMenuItemClickListener(new OnMenuItemClickListener() { @Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.context_copy:
Toast.makeText(MainActivity.this, "select copy ", Toast.LENGTH_SHORT).show();
return true;
case R.id.context_delete:
Toast.makeText(MainActivity.this, " select delete ", Toast.LENGTH_SHORT).show();
return true;
case R.id.context_edit:
Toast.makeText(MainActivity.this, " select edit ", Toast.LENGTH_SHORT).show();
return true;
default :
return false;
}
}
});
popup.getMenuInflater().inflate(R.menu.contextmenu,popup.getMenu());
popup.show();
}

  效果展示,Android4.0:

  源码下载

总结

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

Android--Menus的更多相关文章

  1. Android Contextual Menus之二:contextual action mode

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

  2. Android Contextual Menus之一:floating context menu

    Android Contextual Menus之一:floating context menu 上下文菜单 上下文相关的菜单(contextual menu)用来提供影响UI中特定item或者con ...

  3. Android基本控件之Menus

    在我们的手机中有很多样式的菜单,比如:我们的短信界面,每条短信,我们长按都会出现一个菜单,还有很多的种类.那么现在,我们就来详细的讨论一下安卓中的菜单 Android的控件中就有这么一个,叫做Menu ...

  4. 【Android】5.6 弹出菜单(PopUp Menus)

    分类:C#.Android.VS2015: 创建日期:2016-02-07 一.简介 功能描述:用户单击按钮弹出菜单.当用户选择一个菜单项,会触发MenuItemClick事件并让弹出的菜单消失:如果 ...

  5. [虾扯蛋] android界面框架-Window

    从纯sdk及framwork的角度看,android中界面框架相关的类型有:Window,WindowManager,View等.下面就以这几个类为出发点来概览下安卓开发的"界面架构&quo ...

  6. Android菜单项内容大全

    一.介绍: 菜单是许多应用中常见的用户界面组件. Android3.0版本以前,Android设备会提供一个专用"菜单"按钮呈现常用的一些用户操作, Android3.0版本以后, ...

  7. Android Studio快速开发之道

    概述 现如今开发越来越追求效率和节奏,节省出时间做更多的事情,除了开发技术上的封装等,开发工具的使用技巧也是很重要的,今天就根据自己的经验来给大家介绍一下Android Studio快速开发之道. P ...

  8. [Android] Visual Studio Emulator For Android 相关

    1.修改设备名 C:\Users\[用户名]\AppData\Local\Microsoft\VisualStudioEmulator\Android\Containers\Local\Devices ...

  9. Android Lint Checks

    Android Lint Checks Here are the current list of checks that lint performs as of Android Studio 2.3 ...

  10. Android Studio各种快捷功能及好用的插件

    转载:http://www.jianshu.com/p/c439605a4364 概述 现如今开发越来越追求效率和节奏,节省出时间做更多的事情,除了开发技术上的封装等,开发工具的使用技巧也是很重要的, ...

随机推荐

  1. Robot Framework+python的安装,配置,环境搭建(纯白篇)

    弄了大半天 终于把-Robot Framework-弄好了,总是一个发现问题,一个一个去解决的过程,只是时间嘛,咳咳咳咳 言归正传 第一. 记住了 Robot Framework 的库 只支持 pyt ...

  2. Atcoder Beginner Contest 070 D - Transit Tree Path

    题意:n个点,n-1条边,组成一个无向的联通图,然后给出q和k,q次询问,每次给出两个点,问这两个点之间的最短距离但必须经过k点. 思路:我当时是用优化的Dijkstra写的(当天刚学的),求出k点到 ...

  3. angularjs ng-bind-html的用法总结

    angular中的$sanitize服务. 此服务依赖于ngSanitize模块.(这个模块需要加载angular-sanitize.js插件) 要学习这个服务,先要了解另一个指令: ng-bing- ...

  4. Runnable和Callable 的区别

    Runnable和Callable 的区别 01.Runnable接口中只有一个run()没有返回值 没有声明异常   Callable接口中只有一个call()有返回值 有声明异常 02.Calla ...

  5. TCP和UDP的优缺点

    TCP: 优点: 全双工的可靠连接,使得发送的数据有序.不重复.无差错.不丢失,提供的是可靠的服务: 提供确认重传机制.流量控制和拥塞控制,保证网络的稳定可靠性: 缺点: 每次通信都要建立连接,占用系 ...

  6. 命令更新emacs

    sudo apt-add-repository -y ppa:adrozdoff/emacs sudo apt update sudo apt install emacs25

  7. python random 模块

    http://blog.csdn.net/m0_38061927/article/details/75335069

  8. 服务器windows2008系统登录报错:由于远程桌面服务当前正忙,因此无法完成您尝试的任务。请在...

    1.问题描述:windows server 2008服务器通过远程桌面登录时很慢,登录不进去,把远程桌面关掉后,再用远程桌面登录时,出现下图提示. 把服务器接上显示器键盘鼠标后,卡在系统登录的欢迎界面 ...

  9. UML顺序图知识点介绍(Sequence Diagram)

    消息 调用消息 调用(procedure call)消息的发送者把控制传递给消息的接收者,然后停止活动,等待消息接受者放弃会返回控制 在Rational Rose(2016版本如图所示) 异步消息 异 ...

  10. Kali 2017 使用SSH进行远程登录 设置 ssh 开机自启动

    一.配置SSH参数 修改sshd_config文件,命令为: vi /etc/ssh/sshd_config 输入“ /Pass ”回车搜索 找到#PasswordAuthentication no的 ...