在android3.0以后,安卓设备不在提供物理的菜单按键,同时,android应用提供了另外的菜单实现机制,来替代之前的菜单创建方式。安卓设备中,平常可以使用长按住某个内容弹出菜单选项。这就是我们需要学习的Contextual Menu上下文菜单。
API中介绍了2中上下文菜单的创建:
- 1.漂浮型的上下文菜单
- 2.顶部的上下文菜单
着重介绍漂浮型的上下文菜单,引用原生的android官方文档:
Creating a floating context menu
To provide a floating context menu:
Register the View
to which the context menu should be associated by calling registerForContextMenu()
and pass it the View
.
- If your activity uses a
ListView
orGridView
and you want each item to provide the same context menu, register all items for a context menu by passing theListView
orGridView
toregisterForContextMenu()
.
第一步:提供上下文菜单的View,调用registerForContextMenu()
方法,将View作为参数传递进去。如果你的activity使用ListView或者GridView,你需要遍历每一个View中的内容并提供相同的上下文菜单 context munu, 如果需要为所有的ListView或者GridView注册上下文菜单,你需要将整个View放置进registerForContextMenu()方法中。
- Implement the
onCreateContextMenu()
method in yourActivity
orFragment
.
When the registered view receives a long-click event, the system calls your onCreateContextMenu()
method. This is where you define the menu items, usually by inflating a menu resource. For example:
第二步:当被注册的View接收到长按操作时,系统将会调用onCreateContextMenu()方法,通过使用浮动上下文菜单资源来展示你所定义的上下文菜单。
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.context_menu, menu);
}
MenuInflater
allows you to inflate the context menu from a menu resource. The callback method parameters include the View
that the user selected and a ContextMenu.ContextMenuInfo
object that provides additional information about the item selected. If your activity has several views that each provide a different context menu, you might use these parameters to determine which context menu to inflate.
MenuInflater允许用户从menu资源中填充上下文菜单,这个毁掉方法的参数包含提供用户选择的View和ContextMenuInfo对象,这个ContextMenuInfo对象提供有关于与被选择项的重要信息,如果你的activity有几个View,同时每个View都提供不同的上下文菜单,你可能就需要用到这些参数来判定上下文菜单。
Implement onContextItemSelected()
.
When the user selects a menu item, the system calls this method so you can perform the appropriate action. For example:
@Override
public boolean onContextItemSelected(MenuItem item) {
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
switch (item.getItemId()) {
case R.id.edit:
editNote(info.id);
return true;
case R.id.delete:
deleteNote(info.id);
return true;
default:
return super.onContextItemSelected(item);
}
}
- The
getItemId()
method queries the ID for the selected menu item, which you should assign to each menu item in XML using theandroid:id
attribute, as shown in the section about Defining a Menu in XML.
When you successfully handle a menu item, return true
. If you don't handle the menu item, you should pass the menu item to the superclass implementation. If your activity includes fragments, the activity receives this callback first. By calling the superclass when unhandled, the system passes the event to the respective callback method in each fragment, one at a time (in the order each fragment was added) until true
or false
is returned. (The default implementation for Activity
and android.app.Fragment
return false
, so you should always call the superclass when unhandled.)
第三步:实现onContextItemSelected()方法,当用户选择一个上下文菜单选项时,系统将会回调这个方法。因此你能够执行一些合适的动作。getItemId()方法可以查询到被用户选择的菜单项ID,因此你需要在上下问菜单的xml文件中分别绑定adroid:id属性。
当你成功操作一个菜单选项时,返回true,如果你没有执行某个菜单选项,你应该调用菜单选项的父类实现。如:super.onContextItemSelected(item)。如果你的acitivity包含碎片,这个activity首先接受回调。通过调用父类未进行的操作,系统在鸽子的碎片管理中通过鸽子的回调方法执行相应的动作。
下面是我在学习中写的一些示例代码,供日后查阅:
上下文菜单定义的main.xml:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 <menu xmlns:android="http://schemas.android.com/apk/res/android" > 2 3 <item 4 android:id="@+id/edit" 5 android:orderInCategory="100" 6 android:showAsAction="never" 7 android:title="编辑"/> 8 <item 9 android:id="@+id/share" 10 android:orderInCategory="100" 11 android:showAsAction="never" 12 android:title="分享"/> 13 <item 14 android:id="@+id/del" 15 android:orderInCategory="100" 16 android:showAsAction="never" 17 android:title="删除"/> 18 19 </menu>
窗体layout的activity_main.xml:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:paddingBottom="@dimen/activity_vertical_margin" 6 android:paddingLeft="@dimen/activity_horizontal_margin" 7 android:paddingRight="@dimen/activity_horizontal_margin" 8 android:paddingTop="@dimen/activity_vertical_margin" 9 tools:context=".MainActivity" > 10 11 <ListView 12 android:id="@+id/listView1" 13 android:layout_width="match_parent" 14 android:layout_height="match_parent" 15 android:layout_alignParentLeft="true" 16 android:layout_alignParentTop="true" 17 android:layout_marginLeft="16dp" > 18 </ListView> 19 20 </RelativeLayout>
activity:
1 package com.example.android_menu_context; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 import android.app.Activity; 7 import android.os.Bundle; 8 import android.view.ContextMenu; 9 import android.view.ContextMenu.ContextMenuInfo; 10 import android.view.MenuItem; 11 import android.view.View; 12 import android.widget.AdapterView.AdapterContextMenuInfo; 13 import android.widget.ArrayAdapter; 14 import android.widget.ListView; 15 import android.widget.Toast; 16 17 /** 18 * @author xiaowu 19 * NOTE:为view添加上下文菜单 20 */ 21 public class MainActivity extends Activity { 22 private ListView listView; 23 private ArrayAdapter<String> adapter; 24 25 @Override 26 protected void onCreate(Bundle savedInstanceState) { 27 super.onCreate(savedInstanceState); 28 setContentView(R.layout.activity_main); 29 listView = (ListView) findViewById(R.id.listView1); 30 adapter = new ArrayAdapter<String>(this, 31 android.R.layout.simple_list_item_1, getData()); 32 // 第一步:创建上下文菜单registerForContextMenu(View view) :所有的View的子控件都可以加上下文菜单 33 // 同时需要重写:onCreateContextMenu(ContextMenu menu, View v,ContextMenuInfo 34 // menuInfo)方法 35 registerForContextMenu(listView); 36 listView.setAdapter(adapter); 37 } 38 39 //第二步: 创建上下文菜单按钮 40 @Override 41 public void onCreateContextMenu(ContextMenu menu, View v, 42 ContextMenuInfo menuInfo) { 43 // TODO Auto-generated method stub 44 super.onCreateContextMenu(menu, v, menuInfo); 45 getMenuInflater().inflate(R.menu.main, menu); 46 47 } 48 49 //第三步:处理上下文菜单选中后的点击事件 50 @Override 51 public boolean onContextItemSelected(MenuItem item) { 52 // TODO Auto-generated method stub 53 AdapterContextMenuInfo info = (AdapterContextMenuInfo) item 54 .getMenuInfo(); 55 //获取选中的listView中的item内容 56 String value = adapter.getItem(info.position); 57 switch (item.getItemId()) { 58 case R.id.edit: 59 Toast.makeText(MainActivity.this, "edit-->" + value, 0) 60 .show(); 61 break; 62 case R.id.del: 63 Toast.makeText(MainActivity.this, "del-->" + value, 0) 64 .show(); 65 break; 66 case R.id.share: 67 Toast.makeText(MainActivity.this, "share-->" + value, 0) 68 .show(); 69 break; 70 default: 71 break; 72 } 73 return super.onContextItemSelected(item); 74 } 75 76 // 准备数组适配器的数据 77 public List<String> getData() { 78 List<String> list = new ArrayList<String>(); 79 for (int i = 0; i < 5; i++) { 80 list.add("jack" + i); 81 } 82 return list; 83 } 84 85 // 不需要按钮的方式触发菜单,将该方法屏蔽 86 // @Override 87 // public boolean onCreateOptionsMenu(Menu menu) { 88 // // Inflate the menu; this adds items to the action bar if it is present. 89 // getMenuInflater().inflate(R.menu.main, menu); 90 // return true; 91 // } 92 93 }