1、Android菜单的使用
(在Android中总共有三种类型的菜单:选项菜单,子菜单,上下文菜单)
1.1、选项菜单(实现方式一)
(1)首先在src->menu->main.xml文件中创建菜单项。创建菜单项的标签是
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.example.androidstudy.MainActivity" >
<!-- 在菜单中添加两个菜单项,使用android:id标签设置这个菜单项的唯一标识,使用android:title标签设置这个菜单项的内容 -->
<!-- 使用android:icon来设置菜单中显示的图片 -->
<item
android:id="@+id/menu_add"
android:title="Add"
android:icon="@android:drawable/ic_menu_add"/>
<item
android:id="@+id/menu_wallaper"
android:title="Wallpaper"
android:icon="@android:drawable/ic_menu_gallery"/>
<item
android:id="@+id/menu_search"
android:title="Search"
android:icon="@android:drawable/ic_search_category_default"/>
<item
android:id="@+id/menu_setting"
android:title="Settings"
android:icon="@android:drawable/ic_menu_preferences"/>
</menu>
(2)在需要使用菜单的Activity中重写两个方法:onCreateOptionsMenu()方法和onOpentionsItemSelected()方法:
/** 用于设置菜单是有显示,如果返回true则显示菜单,返回false不显示菜单
说明:MenuInflater是用来实例化Menu目录下的Menu布局文件的,MenuInflater获取方法只有一种:Activity.getMenuInflater();其次,MenuInflater.inflater(int menuRes,Menumenu)(这里不代表inflater就是static方法,可以这样调用,只是为了描述方便)用来给当前活动创建菜单,inflate()方法接受两个参数,第一个参数用于指定我们通过那个资源文件来创建菜单,第二个参数用于指定我们的菜单项将被添加到那一个Menu对象中 */
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater mInflater = this.getMenuInflater();
mInflater.inflate(R.menu.main, menu);
setIconEnable(menu,true);
return true;
}
/**
* 菜单项被选中单击时触发该方法
*/
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_add:
Toast.makeText(this, "You Click one", Toast.LENGTH_SHORT).show();
break;
case R.id.menu_wallaper:
Toast.makeText(this, "You Click two", Toast.LENGTH_SHORT).show();
break;
case R.id.menu_search:
Toast.makeText(this, "You Click two", Toast.LENGTH_SHORT).show();
break;
case R.id.menu_setting:
Toast.makeText(this, "You Click two", Toast.LENGTH_SHORT).show();
break;
}
return true;
}
/**
* 设置菜单中的图片是否显示
* 在Android4.0系统中,创建菜单Menu,通过setIcon方法给菜单添加图标是无效的, 图标没有显出来,2.3系统中是可以显示出来的。这个问题的根本原因在于4.0系统中,涉及到菜单的源码类 MenuBuilder做了改变,mOptionalIconsVisible成员初始值默认为false,这就是为什么给菜单设置图标没有效果的原因;所以,只要我们在创建菜单时通过调用setOptionalIconsVisible方法设置mOptionalIconsVisible为true就可以了;这时候问题来了,要想调用该方法,就需要创建MenuBuilder对象,但是,我们是无法在开发的应用程序中创建MenuBuilder这个对象(MenuBuilder为系统内部的框架类)。这时候就需要考虑用反射了,在代码运行创建菜单的时候通过反射调用setOptionalIconsVisible 方法设置mOptionalIconsVisible为true,然后在给菜单添加Icon,这样就可以在菜单中显示添加的图标了
* @param menu 需要显示图片的菜单对象
* @param enable 设置是否显示图片
*/
private void setIconEnable(Menu menu, boolean enable) {
try {
//通过类名得到这个类的Class对象,然后通过代表这个类的Class对象找到名为setOptionalIconsVisible的方法
Class<?> clazz = Class
.forName("com.android.internal.view.menu.MenuBuilder");
Method m = clazz.getDeclaredMethod("setOptionalIconsVisible",
boolean.class);
m.setAccessible(true);
// MenuBuilder实现Menu接口,创建菜单时,传进来的menu其实就是MenuBuilder对象(java的多态特征)
m.invoke(menu, enable);
} catch (Exception e) {
e.printStackTrace();
}
}
这样就可以创建一个选项菜单,实现的效果如下:
(实现方式二:在Java代码中创建Menu,而不是用.xml文件)
public class BaseActivity2 extends Activity {
// 点击菜单选项的常量Id
private static final int menu1 = 1;
private static final int menu2 = 2;
private static final int menu3 = 3;
private static final int menu4 = 4;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(R.layout.activity_base);
}
// -------------------------------------------这部分为菜单选项----
/**
* ①:直接去覆盖public boolean onCreateOptionsMenu(Menu menu) { code......},
* 这个方法,需要注意的是,这个方法如果覆盖的了,只会被创建一次,也就是说, 选项菜单只会去被实例化一次,,,之后就不会被去调用了
* ②:调用Menu中的add()方法,来添加每一个菜单选项, add(groupId, itemId, order, titleRes)
* group: 选项组号,一般都设置成0就OK啦 itenId: 选项的Id 很重要 order:顺序,一般来说都设置0就行了 titelRes:
* 选项的标题名字 ③:当我们去点击某项的选项的时候,覆盖重写onOptionsItemSelected(MenuItem
* item)这个方法去实现点击事件
* @param group : 选项组号,一般都设置成0就OK啦
* @param itenId : 选项的Id 很重要
* @param order :顺序,一般来说都设置0就行了
* @param titelRes : 选项的标题名字 */
@Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, menu1, 0, "Menu1").setIcon(android.R.drawable.ic_menu_add);
menu.add(0, menu2, 0, "Menu2").setIcon(android.R.drawable.ic_menu_gallery);
menu.add(0, menu3, 0, "Menu3").setIcon(android.R.drawable.ic_menu_search);
menu.add(0, menu3, 0, "Menu3").setIcon(android.R.drawable.ic_menu_send);
setIconEnable(menu, true);
return true;
}
/**
* 菜单项被选中单击时触发该方法
*/
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case menu1:
Toast.makeText(this, "你点击Menu1", Toast.LENGTH_LONG).show();
break;
case menu2:
Toast.makeText(this, "你点击Menu2", Toast.LENGTH_LONG).show();
break;
case menu3:
Toast.makeText(this, "你点击Menu3", Toast.LENGTH_LONG).show();
break;
case menu4:
Toast.makeText(this, "你点击Menu4", Toast.LENGTH_LONG).show();
break;
}
return true;
}
/**
* 设置菜单中的图片是否显示 在Android4.0系统中,创建菜单Menu,通过setIcon方法给菜单添加图标是无效的, 图标没有显出来,2.3系统中是可以显示出来的。这个问题的根本原因在于4.0系统中, 涉及到菜单的源码类 MenuBuilder做了改变,mOptionalIconsVisible成员初始值默认为false,这就是为什么给菜单设置图标没有效果的原因;所以,只要我们在创建菜单时通过调用setOptionalIconsVisible方法设置mOptionalIconsVisible为true就可以了; 这时候问题来了,要想调用该方法,就需要创建MenuBuilder对象,但是,我们是无法在开发的应用程序中创建MenuBuilder这个对象(MenuBuilder为系统内部的框架类)。这时候就需要考虑用反射了,在代码运行创建菜单的时候通过反射调用setOptionalIconsVisible方法设置mOptionalIconsVisible为true,然后在给菜单添加Icon,这样就可以在菜单中显示添加的图标了
* @param menu : 需要显示图片的菜单对象
* @param enable: 设置是否显示图片
*/
private void setIconEnable(Menu menu, boolean enable) {
try {
// 通过类名得到这个类的Class对象,然后通过代表这个类的Class对象找到名为setOptionalIconsVisible的方法
Class<?> clazz = Class .forName("com.android.internal.view.menu.MenuBuilder");
Method m = clazz.getDeclaredMethod("setOptionalIconsVisible",
boolean.class);
m.setAccessible(true);
// MenuBuilder实现Menu接口,创建菜单时,传进来的menu其实就是MenuBuilder对象(java的多态特征)
m.invoke(menu, enable);
} catch (Exception e) {
e.printStackTrace();
}
}
实现的效果同上面
1.2、子菜单
/*
* SubMenu(子菜单)
平时我们希望把同一类型的菜单进行分级来显示,这时候我们会用SubMenu.下面的Demo,是创建两个菜单选项,当点击Menu3的时候 会弹出menu1和menu2的菜单
创建一个SubMenu的基本步骤如下:
①: 先去覆盖Activity中的onCreateOptionsMenu()
②:调用addSubMenu()来添加子菜单项,然后调用add()来添加子菜单
③:覆盖onCreateOptionsMenu(Menu menu)menu.getItemId()来获取选项的Id,去响应单击事件
* */
public class SubMenuActivity extends Activity {
private static final int menu3 = 3;
private static final int menu4 = 4;
private static final int menu1 = 1;
private static final int menu2 = 2;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_base);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
SubMenu M3 = menu.addSubMenu("Menu3");
MenuItem M4 = menu.add(0,menu4,0,"Menu4");
M3.add(0, menu1, 0, "Menu1").setIcon(android.R.drawable.ic_menu_add);
M3.add(0, menu2, 0, "Menu2").setIcon(android.R.drawable.ic_menu_search);
M4.setIcon(android.R.drawable.ic_menu_gallery);
setIconEnable(menu, true);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case menu1:
Toast.makeText(this, "你点击的是Menu1", Toast.LENGTH_LONG).show();
break;
case menu2:
Toast.makeText(this, "你点击的是Menu2", Toast.LENGTH_LONG).show();
break;
case menu4:
Toast.makeText(this, "你点击的是Menu4", Toast.LENGTH_SHORT).show();
break;
}
return true;
}
private void setIconEnable(Menu menu, boolean enable) {
try {
// 通过类名得到这个类的Class对象,然后通过代表这个类的Class对象找到名为setOptionalIconsVisible的方法
Class<?> clazz = Class .forName("com.android.internal.view.menu.MenuBuilder");
Method m = clazz.getDeclaredMethod("setOptionalIconsVisible",
boolean.class);
m.setAccessible(true);
// MenuBuilder实现Menu接口,创建菜单时,传进来的menu其实就是MenuBuilder对象(java的多态特征)
m.invoke(menu, enable);
} catch (Exception e) {
e.printStackTrace();
}
}
运行结果:
1.3、上下文菜单
/*
* ContexgMenu(上下文菜单)
首先什么是上下文菜单,当我们长时间按住屏幕的时候,会弹出菜单,那个就是ContextMenu();
看先文档中对创建ContextMenu()的方法:
【注】 长按按钮,来显示上下文菜单我们必须要去调用 registerForContextMenu(View) ,onCreateContextMenu(ContextMenu, View, ContextMenu.ContextMenuInfo)
* */
public class ContextMenuActivity extends Activity{
private static final int menu1 = 1;
private static final int menu2 = 2;
private static final int menu3 = 3;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//将指定的xml文件转换为View对象
LayoutInflater layoutInf = this.getLayoutInflater();
View view = layoutInf.inflate(R.layout.activity_main, null);
FrameLayout linearLayout = (FrameLayout)this.findViewById(R.id.container);
//为这个View注册上下文菜单
registerForContextMenu(linearLayout);
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
menu.add(0, menu1, 0, "Menu1");
menu.add(0, menu2, 0, "Menu2");
menu.add(0, menu3, 0, "Menu3");
}
@Override
public boolean onContextItemSelected(MenuItem item) {
switch (item.getItemId()) {
case menu1:
Toast.makeText(this, "你 点击的是Menu1", Toast.LENGTH_LONG).show();
break;
case menu2:
Toast.makeText(this, "你点击的是Menu2", Toast.LENGTH_LONG).show();
break;
case menu3:
Toast.makeText(this, "你点击的是Menu3", Toast.LENGTH_LONG).show();
break;
}
return true;
}
运行的效果: