一 前言
菜单在桌面应用中使用十分广泛,在android中由于屏幕的限制,android 3.0之后,就不要求android手机上必须MENU键,加上ActionBar的出现,菜单在android手机上使用越来越少,那么为什么还要总结这个东西?本人开始做android项目的时候,也感觉这个东西可有可无(基本上都是自定义标题栏),即使在一些项目中出现过,也没有太关注,但学习android而不去了解它,感觉又少点什么,那就简单地了解下,在这里对之前了解的菜单作下总结,其实菜单中有些东西还是蛮有用的例如弹出菜单,在点击一个View控件时,在该控件上方或者下方弹出一个选择框,这时使用弹出菜单就很方便,不必自己去自定义PopupWindow,还比如,长按一个View控件,弹出一个东西,那么就可以使用上下文菜单。
二 菜单类结构关系图
Menu MenuItem菜单项 PopUpMenu 弹出菜单
----ContextMenu上下文菜单
----SubMenu 子菜单
说明,从上面可以看到ContextMenu、SubMenu继承了Menu(其为接口),而MenuItem是一个接口,
ContextMenu、SubMenu、Menu通过add函数添加菜单项时返回它,Menu可以通过addSubMenu函数添加一个子菜单(SubMenu),接下来就是介绍它们的具体用法了。
三 SubMenu、Menu、MenuItem、ContextMenu
1 Menu
它的常有方法:
public MenuItem add(CharSequence title); public MenuItem add(@StringRes int titleRes); 添加一个新的菜单项 public MenuItem add(int groupId, int itemId, int order, CharSequence title); public MenuItem add(int groupId, int itemId, int order, @StringRes int titleRes); 添加一个新的菜单项,这个菜单项将会被添加到id为groupId的菜单组 SubMenu addSubMenu(final CharSequence title); SubMenu addSubMenu(@StringRes final int titleRes); 添加一个新的子菜单 SubMenu addSubMenu(final int groupId, final int itemId, int order, final CharSequence title); SubMenu addSubMenu(int groupId, int itemId, int order, @StringRes int titleRes); 添加一个新的子菜单,这个子菜单将会被添加到id为groupId的菜单组
2 SubMenu
SubMenu继承了Menu,它是子菜单,可以包含1~N个
MenuItem,它不支持菜单项图标,不支持子菜单。
(1)常用方法有:
public SubMenu setHeaderTitle(@StringRes int titleRes); public SubMenu setHeaderTitle(CharSequence title); 设置菜单头的标题 public SubMenu setHeaderIcon(@DrawableRes int iconRes); public SubMenu setHeaderIcon(Drawable icon); 设置菜单头的图标 public SubMenu setHeaderView(View view); 给菜单头添加view public SubMenu setIcon(@DrawableRes int iconRes); public SubMenu setIcon(Drawable icon); 设置菜单图标
(2)添加菜单
要重写
onCreateOptionsMenu
方法,如下:
@Override public boolean onCreateOptionsMenu(Menu menu) { //添加子菜单 SubMenu subMenu = menu.addSubMenu("字体大小"); //添加头部图标 android 3。0之后貌似就没有效果了 subMenu.setHeaderIcon(R.mipmap.ic_launcher); //添加图标 android 3。0之后貌似就没有效果了 subMenu.setIcon(R.mipmap.pic_1); //添加头部标题 android 3。0之后貌似就没有效果了 subMenu.setHeaderTitle("选择字体"); //添加菜单项, 其实返回的是 MenuItem FONT_10设置的是item的id subMenu.add(0,FONT_10,0,"10号"); subMenu.add(0,FONT_12,0,"12号"); subMenu.add(0,FONT_14,0,"14号"); subMenu.add(0,FONT_16,0,"16号"); subMenu.add(0,FONT_18,0,"18号"); SubMenu colorMenu = menu.addSubMenu(0,1,0,"字体颜色"); colorMenu.setHeaderIcon(R.mipmap.ic_launcher); colorMenu.setIcon(R.mipmap.pic_1); colorMenu.setHeaderTitle("选择字体颜色"); colorMenu.add(0,FONT_RED,0,"红色"); colorMenu.add(0,FONT_BLUE,0,"蓝色"); colorMenu.add(0,FONT_GREEN,0,"绿色"); // menu.setGroupCheckable(1,true,false); //关联Activity SubMenu intentMenu = menu.addSubMenu("启动Activity"); intentMenu.setHeaderTitle("选择要启动的Activity"); MenuItem menuItem = intentMenu.add("查看ViewAnimator使用"); menuItem.setIntent(new Intent(this,ViewFlipperActivity.class)); return super.onCreateOptionsMenu(menu); }
(3)设置Item监听
需要重写
onOptionsItemSelected
方法,如下:
@Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()){ case FONT_10: txt_menu.setTextSize(10*2); break; case FONT_12: txt_menu.setTextSize(12*2); break; case FONT_14: txt_menu.setTextSize(14*2); break; case FONT_16: txt_menu.setTextSize(16*2); break; case FONT_18: txt_menu.setTextSize(18*2); break; case FONT_RED: txt_menu.setTextColor(Color.RED); break; case FONT_BLUE: txt_menu.setTextColor(Color.BLUE); break; case FONT_GREEN: txt_menu.setTextColor(Color.GREEN); break; } return super.onOptionsItemSelected(item); }
3 ContextMenu
ContextMenu
继承了Menu,
可以包含1~N个
MenuItem,不支持菜单快捷键和
图标。
(1)常用方法有:
public ContextMenu setHeaderTitle(@StringRes int titleRes); public ContextMenu setHeaderTitle(CharSequence title); 设置菜单头的标题 public ContextMenu setHeaderIcon(@DrawableRes int iconRes); public ContextMenu setHeaderIcon(Drawable icon); 设置菜单头的图标 public ContextMenu setHeaderView(View view); 给菜单头添加view
(2)注册上下文菜单
不错,上下文菜单需要注册,参数是View,当长按这个view时,将弹出菜单,如下:
//注册上下文菜单 注册后,长按txt_menu 会弹出上下文菜单,txt_menu为TextVIew对象实例 registerForContextMenu(txt_menu);
(3)添加菜单
需要重写
onOptionsItemSelected方法,如下:
@Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { // super.onCreateContextMenu(menu, v, menuInfo); //添加上下菜单 menu.setHeaderIcon(R.mipmap.ic_launcher); menu.setHeaderIcon(R.mipmap.pic_1); menu.setHeaderTitle("选择背景色"); menu.add(0,FONT_RED,0,"红色"); menu.add(0,FONT_BLUE,0,"蓝色"); menu.add(0,FONT_GREEN,0,"绿色"); }
(4)添加监听
需要重写
onContextItemSelected方法,如下:
@Override public boolean onContextItemSelected(MenuItem item) { switch (item.getItemId()){ case FONT_RED: txt_menu.setBackgroundColor(Color.RED); break; case FONT_BLUE: txt_menu.setBackgroundColor(Color.BLUE); break; case FONT_GREEN: txt_menu.setBackgroundColor(Color.GREEN); break; } return super.onContextItemSelected(item); }
四 使用XML文件定义菜单(推荐)
在Java中直接使用菜单,显得比较臃肿,android使用XML文件很好的解决了这个问题。
1 标签与属性
<menu></menu>元素:菜单;
<item.../>元素:定义菜单项;
<group.../>子元素:将多个
<item.../>元素包装成一个菜单组;
<group.../>下的属性有:
checkableBehavior:指定改菜单组的选择行为,值为none(不可选)、all(多选)、single(单选);menuCategory:指定菜单的优先级,值可为container、system、secondary、alternative;
visible:指定是否可见;enable:指定是否可用;
<item.../>
下的属性有:
android:id:菜单项的唯一标识;android: title:菜单项标题;android: icon:菜单项图标;android: alphabeticShortCut:为菜单项指定字符快捷键;android: numericShortCut: 为菜单项指定数学快捷键;android: checkable:指定菜单项是否可选;android: checked:指定改菜单项默认是否已经勾选;android: visible:指定是否可见;android: enable:指定是否可用;
示例如下:
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <!--在item下使用menu相当定义个子菜单--> <item android:title="字体大小" android:icon="@mipmap/ic_launcher"> <menu> <!--属性checkableBehavior定义菜单行为 single 单选,all多选,none 不可选--> <group android:id="@+id/group_fount" android:checkableBehavior="single"> <item android:id="@+id/fount_10" android:title="10号" /> <item android:id="@+id/fount_12" android:title="12号" /> <item android:id="@+id/fount_14" android:title="14号" /> <item android:id="@+id/fount_16" android:title="16号" /> <item android:id="@+id/fount_18" android:title="18号" /> </group> </menu> </item> <item android:title="字体颜色" android:icon="@mipmap/pic_1"> <menu> <group android:id="@+id/group_color" android:checkableBehavior="single"> <item android:id="@+id/f_color_17" android:title="红色"/> <item android:id="@+id/f_color_18" android:title="蓝色"/> <item android:id="@+id/f_color_19" android:title="绿色"/> </group> </menu> </item> </menu>
2 添加菜单
和上面一样,要重写
onCreateOptionsMenu
方法,但它需要菜单加载器MenuInflater加载布局,如下:
@Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = new MenuInflater(this); inflater.inflate(R.menu.normal_menu,menu); return super.onCreateOptionsMenu(menu); }
3 添加监听
和上面一样
需要重写
onOptionsItemSelected
方法,然后跟菜单项的id交由不同case进行处理,如下:
@Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()){ case R.id.fount_10: txt_menu.setTextSize(10*2); break; case R.id.fount_12: txt_menu.setTextSize(12*2); break; case R.id.fount_14: txt_menu.setTextSize(14*2); break; case R.id.fount_16: txt_menu.setTextSize(16*2); break; case R.id.fount_18: txt_menu.setTextSize(18*2); break; case R.id.f_color_17: txt_menu.setTextColor(Color.RED); break; case R.id.f_color_18: txt_menu.setTextColor(Color.BLUE); break; case R.id.f_color_19: txt_menu.setTextColor(Color.GREEN); break; } return super.onOptionsItemSelected(item); }
参考示例源码点击查看。
五 PopupMenu
最后一个东西,弹出菜单,顾名思义它将会显示在一个view的上方或下方,使用步骤如下:
(1)调用构造函数PopupMenu(Context context,View anchor),new一个
PopupMenu对象实例,
anchor是激发该菜单的组件;
(2)调用MenuInflater的inflater()的函数加载菜单XML文件;
(3)调用show()函数显示菜单;
1 创建PopupMenu对象实例
//txt_menu为TextVIew对象实例 popupMenu = new PopupMenu(PopUpMenuTestActivity.this,txt_menu);
2 加载菜单XML文件
getMenuInflater().inflate(R.menu.popup_menu,popupMenu.getMenu());
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <!--在item下使用menu相当定义个子菜单--> <item android:title="字体大小" android:icon="@mipmap/ic_launcher"> <menu> <!--属性checkableBehavior定义菜单行为 single 单选,all多选,none 不可选--> <group android:id="@+id/group_fount" android:checkableBehavior="none"> <item android:id="@+id/fount_10" android:title="10号" /> <item android:id="@+id/fount_12" android:title="12号" /> <item android:id="@+id/fount_14" android:title="14号" /> <item android:id="@+id/fount_16" android:title="16号" /> <item android:id="@+id/fount_18" android:title="18号" /> </group> </menu> </item> </menu>
3 激发View显示菜单
txt_menu.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { popupMenu.show(); } });
4 添加监听
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { switch (item.getItemId()){ case R.id.fount_10: txt_menu.setTextSize(10*2); break; case R.id.fount_12: txt_menu.setTextSize(12*2); break; case R.id.fount_14: txt_menu.setTextSize(14*2); break; case R.id.fount_16: txt_menu.setTextSize(16*2); break; case R.id.fount_18: txt_menu.setTextSize(18*2); break; } return true; } });