一、OptionMenu(选项菜单) 






android中最常用的就是选项菜单(optionsMenu), 该菜单在点击 menu 按键后会在对应的Activity底部显示出来。并且每个Activity 都可以选择处理这一请求,一般情况下,选项菜单最多显示2排每排3个菜单项,这些菜单项有文字有图标,也被称作Icon Menus,如果多于6项,从第六项开始会被隐藏,第六项会出现一个More,点击More才出现第六项及以后的菜单项.      



以上陈述的是在3.0版之前选项菜单的显示形式,3.0版后由于加入了新的属性ActionBar,添加选项菜单后被显示在ActionBar中,手机上物理按键也渐渐的被去掉。选项菜单还可设置显示在屏幕下方。






Activity类的 public boolean onCreateOptionsMenu(Menu menu){ } 方法用来创建选项菜单,一般需要将创建选项菜单的代码放在onCreateOptionsMenu()方法里边,通过Menu接口的add方法可以添加一个选项菜单,该方法有四种重载形式:



public MenuItem add(CharSequence title);
public MenuItem add(int titleRes);
public MenuItem add(int groupId, int itemId, int order, CharSequence title);
public MenuItem add(int groupId, int itemId, int order, int titleRes);



add方法最多有4个参数,这些参数的含义如下:



groupId:菜单项的分组ID,该参数一般用于带选项按钮的菜单。参数值可以是负整数、0和正整数。



itemId:当前添加的菜单项的ID。该参数值可以是负整数、0和正整数。



order:菜单显示顺序。Android系统在显示菜单项时,根据order参数的值按升序从左到右、从上到下显示菜单项。参数值必须是0和正整数,不能为负整数。



titleRes或title:菜单项标题的字符串资源ID或字符串。



如果使用add方法的前两种重载形式,groupId、itemId和order三个参数的值都为0。这时菜单项的显示顺序就是菜单项的添加顺序。下面的代码添加了3个选项菜单项:



public boolean onCreateOptionsMenu(Menu menu) {
	menu.add(1, 1, 1, "菜单项1");  
	menu.add(1, 2, 2, "菜单项2");  
	menu.add(1, 3, 3, "菜单项3"); 
	return true;
}

通过查阅api文档可知,add方法的返回值是一个MenuItem对象,每一个MenuItem对象对应一个菜单项。可以通过MenuItem接口的相应方法来设置与菜单项相关的内容, 

例如,下面的代码设置了菜单项的图像:


MenuItem deleteMenuItem = menu.add(1, 1, "删除");  
deleteMenuItem.setIcon(R.drawable.delete);


我们还可以使用MenuItem接口的setIntent方法将一个activity与菜单项关联,setIntent方法的定义如下:


public MenuItem setIntent(Intent intent);



将一个Activity与菜单项关联后,单击该菜单项,系统会调用startActivity方法显示与菜单项关联的Activity。



下面的代码将AddActivity与"添加"菜单项关联,单击"添加"菜单项,系统就会显示AddActivity。



MenuItem addMenuItem = menu.add(1, 1, 1, "添加");  
//  将AddActivity与“添加”菜单项进行关联  
addMenuItem.setIntent(new Intent(this, AddActivity.class));



但是,如果设置了菜单项的单击事件,则与菜单项关联的Activity将失效。也就是说,系统将会调用单击事件方法,而不会显示与菜单项关联的Activity了。






二、ContextMenu(上下文菜单)  






Android的上下文菜单,当一个视图注册到一个上下文菜单时,执行一个在该视图对象上的“长按”动作,将出现一个提供相关功能的浮动菜单。上下文菜单可被注册到任何视图中。但不支持图标或快捷键。示例代码:



menu.add(1, 1, 1, "菜单项1").setOnMenuItemClickListener(this); 
public boolean onMenuItemClick(MenuItem item) {
	if (item.getItemId() == 3) {
		 Toast.makeText(this, "你选的是dajb", Toast.LENGTH_SHORT).show();
		  return true;
	}
	return false;
}



  



三、SubMenu(子菜单)  



SubMenu(子菜单)是在选项菜单的基础上增加的菜单。



子菜单不支持嵌套,即子菜单中不能再包括其他子菜单。一个Menu对象可以拥有0或多个SubMenu,通过调用Menu.addSubMenu方法将SubMenu添加到当前Menu中。



在SubMenu添加MenuItem的方式和在Menu中添加MenuItem方式一样,因为SubMenu是Menu的子类,但是SubMenu里不能再添加SubMenu。



与add()方法一样它有四个重载方法,参数也同出一辙。



public abstract SubMenu addSubMenu(int titleRes)
public abstract SubMenu addSubMenu(CharSequence title)
public abstract SubMenu addSubMenu(int groupId, int itemId, int order, int titleRes)
public abstract SubMenu addSubMenu(int groupId, int itemId, int order, CharSequence title)



常用的和menu菜单相关的方法有:



public boolean onCreateOptionsMenu(Menu menu):使用此方法调用OptionsMenu。



public void onOptionsMenuClosed(Menu menu):菜单关闭后发生的动作。



public boolean onPrepareOptionsMenu(Menu menu):选项菜单显示之前onPrepareOptionsMenu方法会被调用,你可以用此方法来根据打当时的情况调整菜单。



public boolean onMenuOpened(int featureId, Menu menu): 菜 单打开后发生的动作。







三种菜单的点击事件 —— 处理菜单点击事件的方法有四种:






第一种、直接复写activity的onOptionsItemSelected方法,这种方法只限于OptionMenu(选项菜单) 和 SubMenu(子菜单)



第二种、直接复写activity的onMenuItemSelected方法,这种方法适用于三种菜单



第三种、先实现android.view.MenuItem.OnMenuItemClickListener接口,然后重写onMenuItemClick(MenuItem item)方法,这种方法只适用于OptionMenu(选项菜单)



第四种、直接复写activity的onContextItemSelected方法,这种方法只适用于ContextMenu(上下文菜单)



这四种方法都有一个MenuItem 类型的item参数,可以根据MenuItem接口的相应方法(例如getTitle和getId)判断单击的是哪个项。






如果同时使用了适用于某一种菜单的所有方法的话:



对于OptionMenu来讲:



当onMenuItemClick返回true时,其余事件全部失效



当onMenuItemClick返回false时,除onContextItemSelected之外的三种方法都会被调用



对于SubMenu(子菜单) 来讲:



无论onMenuItemClick方法返回值是什么,都会调用onMenuItemSelected和onOptionsItemSelected两个方法



而对于ContextMenu来讲:



无论onMenuItemClick方法返回值是什么,都会调用onMenuItemSelected和onContextItemSelected两个方法



 



直接上一个完整示例:



public class MainActivity extends Activity implements OnMenuItemClickListener{
	Button mButton1;
	Button mButton2;
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		mButton1 = (Button)findViewById(R.id.button1);
		mButton2 = (Button)findViewById(R.id.button2);
		// 注册一个视图到上下文菜单
		registerForContextMenu(mButton1);
          	registerForContextMenu(mButton2);
	}
	public boolean onCreateOptionsMenu(Menu menu) {
		//通过Menu接口的add方法可以添加一个OptionMenu(选项菜单) 
		MenuItem menuitem1 = menu.add(0, 1, 1, "menuitem1");
		MenuItem menuitem2 = menu.add(0, 2, 2, "menuitem2");
		//此处通过MenuItem接口的setOnMenuItemClickListener方法可以设置菜单项的单击事件。
		menuitem1.setOnMenuItemClickListener(this);
		menuitem2.setOnMenuItemClickListener(this);
		//添加子菜单
		SubMenu subMenu = menu.addSubMenu(0, 7, 7, "subMenu");
        	subMenu.add(0, 8, 8, "subMenu1");
        	subMenu.add(0, 9, 9, "subMenu2");
       		//使用布局文件的方式增加菜单
       		getMenuInflater().inflate(R.menu.mymenu, menu);
		return super.onCreateOptionsMenu(menu);
	}
	//创建ContextMenu(上下文菜单)  
    	public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
      	        if(v==mButton1){
          		 menu.setHeaderTitle("Context Menu 1");
           		 menu.add(0, 3, 3, "Context Menu 1_1");
           		 menu.add(0, 4, 4, "Context Menu 1_2");
        	}
       		 else if(v==mButton2){
           		 menu.setHeaderTitle("Context Menu 2");
           		 menu.add(0, 5, 5, "Context Menu 2_1");
           		 menu.add(0, 6, 6, "Context Menu 2_2");
        	}
        	super.onCreateContextMenu(menu, v, menuInfo);
        }
	//直接复写activity的onOptionsItemSelected方法,这种方法只限于OptionMenu(选项菜单) 和 SubMenu(子菜单)
        public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()){
		case 1:
			 System.out.println("onOptionsItemSelected....OptionMenu....menuitem1");
		         break;
	        case 2:
	    		 System.out.println("onOptionsItemSelected....OptionMenu....menuitem2");
		         break;
		case 3:
			 System.out.println("onOptionsItemSelected....ContextMenu....Context Menu 1_1");
		    	 break;
		case 5:
			 System.out.println("onOptionsItemSelected....ContextMenu....Context Menu 2_1");
		    	 break;
		case 8:
			 System.out.println("onOptionsItemSelected....SubMenu....subMenu1");
		    	 break;
		case 9:
			 System.out.println("onOptionsItemSelected....SubMenu....subMenu2");
		     	 break;
		}
	    	return false;
        }
	//直接复写activity的onMenuItemSelected方法,这种方法适用于三种菜单
	public boolean onMenuItemSelected(int featureId, MenuItem item) {
		switch (item.getItemId()){
		case 1:
			 System.out.println("onMenuItemSelected....OptionMenu....menuitem1");
		     	 break;
	    	case 2:
	    	 	System.out.println("onMenuItemSelected....OptionMenu....menuitem2");
		        break;
		case 3:
			 System.out.println("onMenuItemSelected....ContextMenu....Context Menu 1_1");
		    	 break;
		case 5:
			 System.out.println("onMenuItemSelected....ContextMenu....Context Menu 2_1");
		    	 break;
		case 8:
			 System.out.println("onMenuItemSelected....SubMenu....subMenu1");
		     	break;
		case 9:
			 System.out.println("onMenuItemSelected....SubMenu....subMenu2");
		    	 break;
		}
		return super.onMenuItemSelected(featureId, item);
	}
	/*
	菜单项的单击事件类先去实现OnMenuItemClickListener接口,即android.view.MenuItem.OnMenuItemClickListener,
	然后去重写onMenuItemClick(MenuItem item)方法。这种方法只适用于OptionMenu(选项菜单)
	*/
	public boolean onMenuItemClick(MenuItem item) {
		switch (item.getItemId()){
		case 1:
			 System.out.println("onMenuItemClick....OptionMenu....menuitem1");
		    	 break;
	        case 2:
	    		 System.out.println("onMenuItemClick....OptionMenu....menuitem2");
		         break;
		case 3:
			 System.out.println("onMenuItemClick....ContextMenu....Context Menu 1_1");
		         break;
		case 5:
			 System.out.println("onMenuItemClick....ContextMenu....Context Menu 2_1");
		     	 break;
		case 8:
			 System.out.println("onMenuItemClick....SubMenu....subMenu1");
		    	 break;
		case 9:
			 System.out.println("onMenuItemClick....SubMenu....subMenu2");
		     	 break;
		}
		return false;
	}
	//这种方法只适用于ContextMenu(上下文菜单)
	public boolean onContextItemSelected(MenuItem item) {
		switch (item.getItemId()){
	 	case 1:
			 System.out.println("onContextItemSelected....OptionMenu....menuitem1");
			  break;
		 case 2:
		    	 System.out.println("onContextItemSelected....OptionMenu....menuitem2");
			     break;
		  case 3:
			  System.out.println("onContextItemSelected....ContextMenu....Context Menu 1_1");
			   break;
		  case 5:
			  System.out.println("onContextItemSelected....ContextMenu....Context Menu 2_1");
			   break;
		   case 8:
			   System.out.println("onContextItemSelected....SubMenu....subMenu1");
			   break;
		   case 9:
			   System.out.println("onContextItemSelected....SubMenu....subMenu2");
			   break;
		   }
	           return true;
	 }
}



 



自定义menu:






在 Android 中任何视图组件的创建方式都有两种:



1、在XML文件中创建;



2、在代码中创建。



Menu 也不例外,我们既可以在资源文件中声明,也可以在代码中创建。



Android中的3种菜单都可以在XML文件中声明定义,在代码中通过MenuInflater 类来使用。






Menu 资源文件存放于工程的res\menu目录下。通过R.menu.name  的方式来引用。



Menu 资源文件的结构:



  1、<menu>根元素,在<menu>根元素里面会嵌套<item>和<group>子元素,<menu>根元素没有属性。



  2、<item>元素中也可嵌套<menu>形成子菜单。



  3、<group>表示一个菜单组,相同的菜单组可以一起设置其属性,例如visible、enabled和checkable等。



<group>元素的属性说明 如下:



—  id:唯一 标示该菜单组的引用id。



—  menuCategory:对菜单进行分类,定义菜单的优先级,有效值为container、system、secondary和alternative。



—  orderInCategory:一个分类 排序整数。



—  checkableBehavior:选择 行为,单选、多选还是其他。有效值为none、all和single。



—  visible:是否可见,true或者false。



—  enabled:是否可用,true或者false。






<item>表示菜单项,包含在<menu>或<group>中的有效属性。



<item>元素的属性说明如下:



—  id:唯一标示菜单的ID引用。



—  menuCategory:菜单分类。



—  orderInCategory:分类排 序。



—  title:菜单标题字符串。



—  titleCondensed:浓缩标题, 适合标题太长的时候使用。



—  icon: 菜单的图标。



—  alphabeticShortcut:字 符快捷键。



—  numericShortcut:数字快捷键。



—  checkable:是否可选。



—  checked:是否已经被选。



—  visible:是否可见。



—  enabled:是否可用。