Android 菜单:OptionsMenu,ContextMenu,PopupMenu
Menu的功能:给用户提供一个可以进行管理,设置,以及不常用功能的整理和集合;
Menu如何设置:采用XML可以实现(java代码也可以创建);
Menu由Activity来加载和显示的,需要重写Activity的方法;
Activity需要重写方法进行菜单加载,以及菜单点击的处理
菜单可以分为三类:
1,上下文菜单(ContextMenu):长按某一个View,出现的菜单,称为上下文菜单(只出现在屏幕中间),类似于Windows的右键菜单
2,OptionsMenu:在Activity标题栏中,显示的菜单
3,PopupMenu:Android3.0以后添加的心功能,用来改进上下文菜单的显示效果(可显示在任意位置);
OptionsMenu
OptionsMenu是由Activity来加载的,才可以显示在标题栏上,Activity需要重写onCreateOptionsMenu(Menu,Menu)方法,来设置Activity的菜单;
<?xml version="1.0" encoding="utf-8"?> <!--需要在layout中创建menu文件夹,然后创建菜单文件,通过xml描述的菜单--> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <!--名词:菜单(menu),菜单项(menu item)--> <item android:id="@+id/action_sets" android:title="设置" /> <item android:id="@+id/action_help" android:title="help" /> </menu>
/** * !!!这个OptionMenu的创建,只会调用一次 * 当Activity启动之后,需要进行菜单的加载, * 如果是实现了这个方法,并且menu菜单中,添加了菜单项menu item * Activity将会自动的支持菜单的显示; * @param menu * @return true 菜单可以显示,false 菜单不会显示 */ @Override public boolean onCreateOptionsMenu(Menu menu) { //1,加载菜单,使用MenuInflater来加载,对应Activity已经包含一个menuInflater对象,可以直接使用 menuInflater = getMenuInflater(); //解析menu菜单文件,并且自动的将菜单添加到指定的参数2菜单中 menuInflater.inflate(R.menu.main_menu,menu); return true; } /** * 当OptionMenu被选中的时候,回调此方法 * @param item * @return true-->代表当前的菜单点击处理,已经处理过了 */ @Override public boolean onOptionsItemSelected(MenuItem item) { //因为这个方法,所有菜单都公用,所以需要通过menu的id来进行区分 switch (item.getItemId()){ case R.id.action_sets: Toast.makeText(this,"action_sets",Toast.LENGTH_SHORT).show(); break; case R.id.action_help: Toast.makeText(this,"action_help",Toast.LENGTH_SHORT).show(); break; } return true; }
1,程序中onCreateOptionsMenu(Menu menu)方法,Activity自身含有的方法,只要重写该方法,系统会自动完成点击的时间调用;
2,onOptionsItemSelected(MenuItem item)方法为菜单的点击事件
3,MenuItem需要设置Id,来进行点击的判断;
4,菜单项id的通用规则:以“action_”开头,后面附带功能表示的单词;
ContextMenu
1,通常上下文菜单通过手指长按才会显示;
2,弹出一个浮动在界面上方的类似于对话框性质的界面;
3,上下文菜单点击,同样会出发相应的操作;
4,上下文菜单通常都是和点击的条目相关
上下文菜单的特点:针对特定的内容,进行的菜单显示;不同的内容,显示出来的菜单项也不同;
上下文菜单的加载方式:
与OptionMenu类似,都是同时能过回调来设置菜单的;
使用XML描述菜单,通过MenuInflater来加载菜单;
上下文菜单的触发和现实的机制:通过控件的长按来完成的;ListView/GridView默认支持上下文菜单
onCreateContextMenu()方法,通过参数3ContextMenuInfo可以传递附加信息,例如ListView,可以确定当前选择的Item的位置
上下文菜单的注册:
registerForContextMenu(View)---->注册上下文菜单
unregisterForContextMenu(View)--->释放上下文菜单的注册
步骤:
1,注册View来显示ContextMenu
2,实现Activity onCreateContextMenu()就可以显示;
3,处理点击:
点击上下文的时候,通常只有在ListView或者GridView的时候,才能够获取MenuInfo,来判断长按的是哪一项;
对于普通的View而言,菜单无法获取选中的是哪个View,通常需要使用成员变量来实现内容的访问;
onContextItemSelected(MenuItem item)是上下文菜单的点击处理方法,ContextMenuInfo转换AdapterContextMenuInfo获取位置;
Android当中,关于时间的处理,凡是带有Boolean返回类型事件,都有一个含义,如果返回true,事件不会再继续执行public class ContactActivity extends Activity { private ArrayAdapter<String> arrayAdapter; private List<String> items; private ListView lv; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_contact); lv = (ListView) findViewById(R.id.lv); items = new LinkedList<String>(); for (int i = 0; i <50 ; i++) { items.add("item"+i); } arrayAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,items); lv.setAdapter(arrayAdapter); registerForContextMenu(lv); } @Override protected void onDestroy() { unregisterForContextMenu(lv); super.onDestroy(); } /** * 每一个上下文菜单,需要显示的时候,这个方法,就会被调用; * @param menu ContextMenu和Menu类似,里面可以添加多个菜单项; * @param v 实际上就是被长按的那个控件,v不同导致菜单不一样; * @param menuInfo 菜单在创建的时候,附加的信息,只有在listView和GridView item长按的时候才有效 */ @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.context_image_menu,menu); } /** * 类似于onOptionsItemSelected,都是菜单项,点击之后,回调此方法,进行菜单事件的处理 * @param item * @return true-->当前菜单项的处理已经完成了,false-->让Activity自己来处理 */ @Override public boolean onContextItemSelected(MenuItem item) { //从ListView中,长按出发的上下文菜单,每一个Item都会包含一个叫做MenuIfo的数据,这个数据包含了长按menu的位置 switch(item.getItemId()){ case R.id.action_image_save: ContextMenu.ContextMenuInfo menuInfo = item.getMenuInfo(); if(menuInfo!=null){ AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo; int position = info.position; items.remove(position); arrayAdapter.notifyDataSetChanged(); } break; case R.id.action_image_large: ContextMenu.ContextMenuInfo menuInfo1 = item.getMenuInfo(); if(menuInfo1!=null){ AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo1; int position = info.position; Toast.makeText(this,""+position,Toast.LENGTH_SHORT).show(); } break; } return true; } }
PopupMenu
Android3.0以后提出,可以直接显示在制定空间上的菜单,不再需要长按,而是通过代码来指定显示的控件及其位置;
其特点:必须通过创建new PopupMenu(Context,View),第二个参数代表菜单以哪个控件为基准来显示;PopupMenu虽然可以通过setOnMenuItemClickListener来设置菜单的点击事件处理,但是,PopupMenu和ContextMenu一样,都需要获取当前点击位置的信息;
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/action_image_save" android:title="删除" /> <item android:id="@+id/action_image_large" android:title="修改" /> </menu>
public class PopupMenuActivity extends Activity implements PopupMenu.OnMenuItemClickListener { /** * 用于显示的弹出菜单 */ private PopupMenu popupMenu; private MenuInflater menuInflater; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_popup_menu); } /** * 显示PopupMenu * @param view */ public void btnShowPopup(View view) { if(popupMenu==null){ //创建PopupMenu,参数2:指定菜单与哪个控件挨着 popupMenu = new PopupMenu(this,view); //设置菜单项,从xml加载 //获取菜单加载器 menuInflater = popupMenu.getMenuInflater(); menuInflater.inflate(R.menu.context_image_menu,popupMenu.getMenu()); popupMenu.setOnMenuItemClickListener(this); } //显示菜单 popupMenu.show(); } /** * 菜单项 点击的时候的调用 * @param item * @return */ @Override public boolean onMenuItemClick(MenuItem item) { switch(item.getItemId()){ case R.id.action_image_save: Toast.makeText(this,"保存图片",Toast.LENGTH_SHORT).show(); break; } return true; } }