一 前言
菜单在桌面应用中使用十分广泛,在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文件如下:
<?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;
}
});