Android-UI开发之菜单
程序员文章站
2022-06-30 18:19:52
...
一.菜单Menu概述
- OptionsMenu(选项菜单),默认看不到,当用户点击Menu键时,系统才显示应用关联的菜单。
- SubMenu 子菜单
- ContextMenu(上下文菜单),当用户一直按住某一个组件时,该组件关联的上下文菜单就显示出来。
- PopupMenu(弹出式菜单),它会在指定组件上弹出PopupMenu,可以增加多个菜单项,并可以为菜单项增加子菜单。
二.选项菜单与子菜单
1.实现步骤
- Menu菜单接口,SubMenu子菜单,MenuItem菜单项
- add()方法用于添加菜单项
- addSubMenu()用亍添加子菜单
- 添加菜单或子菜单的步骤如下
- 重写Activity的onCreateOptionsMenu(Menu menu)方法,在该方法里面调用Menu对象的方法来添加菜单项或子菜单
- 如果希望应用程序能响应菜单项的单击事件,重写Activity的onOptionsItemSelected(MenuItem mi)方法
2.例子一
public boolean onCreateOptionsMenu(Menu menu) {
try {
Class<?> menuClass = Class.forName("com.android.internal.view.menu.MenuBuilder");
Method menuMethod = menuClass.getDeclaredMethod("setOptionalIconsVisible", boolean.class);
menuMethod.setAccessible(true);
menuMethod.invoke(menu, true);
}catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
MenuItem show_item = menu.add(0, Menu.FIRST, 0, "显示").setIcon(R.drawable.delete);
// MenuItem share_item = menu.add(0, Menu.FIRST+1, 0, "分享");
SubMenu shareMenu = menu.addSubMenu(0, Menu.FIRST+1, 0, "分享").setIcon(R.drawable.delete);
shareMenu.setHeaderIcon(R.drawable.ic_launcher);
shareMenu.setHeaderTitle("分享到...");
shareMenu.add(0, 100, 0, "微信");
shareMenu.add(0, 101, 0, "QQ");
shareMenu.add(0, 102, 0, "新浪微博");
MenuItem detail_item = menu.add(0, Menu.FIRST+2, 0, "详细");
MenuItem delete_item = menu.add(0, Menu.FIRST+3, 0, "删除");
MenuItem help_item = menu.add(0, Menu.FIRST+4, 0, "帮助");
MenuItem save_item = menu.add(0, Menu.FIRST+5, 0, "保存").setIcon(R.drawable.circle);
MenuItem other_item = menu.add(0, Menu.FIRST+6, 0, "其他");
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {//响应选项菜单的点击事件
switch (item.getItemId()) {
case Menu.FIRST:
Toast.makeText(MainActivity.this,"你点击的是显示",Toast.LENGTH_SHORT).show();
break;
case 100:
Toast.makeText(MainActivity.this,"你要分享到微信去",Toast.LENGTH_SHORT).show();
break;
}
return true;
}
3.注意事项
- 超过6个MenuItem时,第6个显示为more,之后的以子菜单式样显示,不再显示图标
- 通过addSubMenu()用亍添加子菜单
- Menu可以包含多个SubMenu,SubMenu可以包含多个MenuItem
- SubMenu不能包含SubMenu,子菜单不能嵌套
- 子菜单可以添加菜单头标题、图标,但菜单项不能显示图标
- 动态改变选项菜单的内容,需重写onPrepareOptionsMenu(Menu)
三.上下文菜单
1.上下文菜单概述
- 类似于普通桌面程序的右键菜单
- 点击界面元素超过2s后自劢出现的菜单
- 可以被注册到任何View对象中(基本控件、布局文件、ListView的某一项等)
2.开发上下文菜单步骤
- 重写Activity的onCreateContextMenu()方法
- 调用Activity的registerForContextMenu(View view)方法为View组件组成上下文菜单
- 重写onContextItemSelected(MenuItem m)方法为菜单项提供响应
3.例子一
首先要在xml中添加一个imageView,这个毫无疑问
重写onCreateContextMenu()
private ImageView imageView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView=(ImageView) findViewById(R.id.imageView1);
registerForContextMenu(imageView);//注册这个是必须的 如果不注册的话点击会没反应
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
switch (v.getId()) {
case R.id.imageView1:
menu.add(0,200,0,"QQ空间");
menu.add(0,201,0,"微信");
menu.add(0,202,0,"朋友圈");
menu.add(0,203,0,"新浪微博");
menu.setHeaderIcon(R.drawable.ic_launcher);
menu.setHeaderTitle("分享到...");
break;
default:
break;
}
}
@Override
public boolean onContextItemSelected(MenuItem item) {
switch (item.getItemId()) {
case 200:
Toast.makeText(this,"你要分享到QQ空间去",Toast.LENGTH_SHORT).show();
break;
}
return true;
}
4.注意事项
- 没有快捷键,不能显示菜单项图标
- 每个Activity有且只有一个Options Menu,它为整个Activity服务
- 上下文菜单的拥有者是Activity中的View,显示地通过registerForContextMenu(View view)来为View指定是否拥有上下文菜单,多个View都可拥有ContextMenu
- onCreateOptionsMenu只在用户第一次按“Menu”键时被调用,而onCreateContextMenu会在用户每一次长按View时被调用
- 视图元素需要向上下文菜单传递一些信息,比如该View对应DB记录的ID等,需要使ContextMenuInfo,并重写getContextMenuInfo()方法
5.使用XML文件定义菜单
- 在res/menu目录下创建xxx.xml菜单布局文件
- 定义菜单资源后,重写onCreateOptionsMenu()、onCreateContextMenu()方法
- 在其中调用MenuInflater对象inflate方法装载指定资源的对应菜单xxx.xml
- 好处
- 简化Java代码,降低耦合
- 为每个菜单项、菜单组分配ID,可扩展性强
- 菜单资源文件放置在/res/menu目录下,根目录是
<item...>:定义菜单项
id、title、icon
checkable、checked、visible、enable
<group...>:将多个<item>包装成一个菜单组
checkableBehavior:none(不可选)、all(多选)、single(单选)
visible:指定该组是否可见
enable:指定该组是否可用
<item../>元素用于定义一份菜单项,<item../>元素又可包含<menu../>元素,位于<item../>元素内部的<menu../>就代表子菜单
(1).例子一
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/mi_close"
android:icon="@drawable/ic_launcher"
android:title="Close"/>
<item
android:id="@+id/mi_no_icon"
android:title="Sans Icon"/>
<item
android:id="@+id/mi_disabled"
android:title="Disabled"/>
<item
android:id="@+id/mi_submenu"
android:title="A Submenu" />
</menu>
public boolean onCreateOptionsMenu(Menu menu) {
try {
Class<?> menuClass = Class.forName("com.android.internal.view.menu.MenuBuilder");
Method menuMethod = menuClass.getDeclaredMethod("setOptionalIconsVisible", boolean.class);
menuMethod.setAccessible(true);
menuMethod.invoke(menu, true);
}catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
MenuInflater menuInflater=getMenuInflater();
menuInflater.inflate(R.menu.mymenu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {//响应选项菜单的点击事件
switch (item.getItemId()) {
case R.id.mi_close:
Toast.makeText(MainActivity.this, "你点击的是关闭", Toast.LENGTH_SHORT).show();
break;
case R.id.mi_disabled:
Toast.makeText(MainActivity.this, "你点击的是Disabled", Toast.LENGTH_SHORT).show();
break;
}
return true;
}
6.Android4.0中setIcon无效的问题
- 原因:菜单的源码类 MenuBuilder做了改变
public class MenuBuilder implements Menu {
...//mOptionalIconsVisible 为true时,才能显示图标
private boolean mOptionalIconsVisible = false;
....
void setOptionalIconsVisible(boolean visible) {
mOptionalIconsVisible = visible;
}
boolean getOptionalIconsVisible() {
return mOptionalIconsVisible;
}
...
}
- 解决方法
- 反射机制,在代码运行创建菜单的时候通过反射调用
//setOptionalIconsVisible方法设置mOptionalIconsVisible为true,然后在给菜单添加Icon即可生效
Class<?> clazz =Class.forName("com.android.internal.view.menu.MenuBuilder");
Method m =clazz.getDeclaredMethod("setOptionalIconsVisible",boolean.class);
m.setAccessible(true);
m.invoke(menu, true);
四.弹出式菜单PopupMenu
1.弹出式菜单概述
- PopupMenu代表弹出菜单,它会在指定组件上弹出PopupMenu。需要在API 11以上的版本中才能使用
- PopupMenu可以增加多个菜单项,可以为菜单项增加子菜单
2.创建PopupMenu步骤
- 调用new PopupMenu(Context context,View anchor)创建下拉菜单,anchor代表要激发该弹出菜单的组件。
- 调用MenuInflater的inflate()方法将菜单资源填充到PopupMenu中
- 调用PopupMenu的show()方法显示弹出式菜单
- 注意:PopupMenu的事件监听OnMenuItemClickListener
3.例子一
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/mi_qq"
android:icon="@drawable/ic_launcher"
android:title="QQ空间"/>
<item
android:id="@+id/mi_friend"
android:title="朋友圈"/>
<item
android:id="@+id/mi_tx"
android:enabled="true"
android:title="腾讯微博"/>
<item
android:id="@+id/mi_xl"
android:title="新浪微博"/>
</menu>
button = (Button) findViewById(R.id.button1);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
PopupMenu popupMenu = new PopupMenu(MenuActivity.this, button);
popupMenu.getMenuInflater().inflate(R.menu.pop_menu, popupMenu.getMenu());
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
// TODO Auto-generated method stub
switch (item.getItemId()) {
case R.id.mi_qq:
Toast.makeText(MenuActivity.this, "你打算分享到QQ空间哇", Toast.LENGTH_SHORT).show();
break;
default:
break;
}
return true;
}
});
popupMenu.show();
}
});
END!!!!!!!!!