Android Contextual Menus之一:floating context menu

上下文菜单

  上下文相关的菜单(contextual menu)用来提供影响UI中特定item或者context frame的动作。

  你可以为任何View提供上下文菜单,但是最常见的使用场景是在ListView、GridView或者其他集合类控件中的项目上,这样用户就可以对特定的项目执行一些直接的操作。

  有两种方式来提供上下文相关的动作:

  1.用悬浮上下文菜单( floating context menu)。

  当用户在支持上下文菜单的View上执行长按动作的时候,菜单以一种悬浮列表的方式出现,类似于对话框。

  用户可以每次选择一个菜单项,执行一个上下文相关的动作。

  2.用上下文相关的动作模式(contextual action mode)。

  这种模式是ActionMode的系统实现,在屏幕上方展示一个上下文相关的action bar,里面有一些action items,可以用来执行选定项目的相关动作。

  当这种模式active时,用户可以一次对多个项目执行操作。

  注意:虽然contextual action mode是更为推崇的一种方式,但是它是Android 3.0(API Level 11)之后才有的,如果要兼容3.0之前的系统,那就应该用floating context menu。

创建floating context menu

  提供悬浮上下文菜单的步骤如下:

  1.通过调用registerForContextMenu()方法注册上下文菜单相关的View。

  如果你的activity中用了ListView或者GridView,而且你想其中的每一个item都提供相同的上下文菜单,那么你可以在registerForContextMenu() 中传递这个ListView或GridView。

  2.在Activity或Fragment中实现 onCreateContextMenu()方法。

  当注册过的View接收到长按事件,系统会调用onCreateContextMenu()方法。

  这里你可以定义菜单项,通常是inflate一个菜单资源,比如:

@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允许你通过inflate menu resource来得到一个上下文菜单。

  这个回调方法的参数包含了一个用户选择的View和一个ContextMenu.ContextMenuInfo对象,该对象提供了当前选择的item的一些附加信息。

  如果你的activity有多个views,每个提供不同的上下文菜单,你可以用这些参数来决定当前要inflate那个上下文菜单。

  3.实现onContextItemSelected()方法

  当用户选择了一个菜单项,系统会调用onContextItemSelected()方法,你可以执行相应的动作,比如:

@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);
}
}

  其中getItemId()方法得到每个菜单项的id值。

  当成功处理了一个菜单项之后,返回true。

  如果你没有处理一个菜单项,你应该把这个菜单项转给它的基类实现。

  如果你的activity包含fragment,activity先接收到这个回调。

  当未处理而调用基类实现时,系统会将这个事件传递到每个fragment各自相应的回调方法中,按照fragment添加的顺序,每次一个,直到返回true或者false。

  Activity和Fragment的默认实现都是返回false,所以你应该永远在未处理的时候调用基类实现。

一个简单的例子

  实现的效果就是长按TextView之后显示一个上下文菜单,含两个菜单项,点击菜单项之后显示Toast。

  Activity代码:

package com.example.mengdd.hellocontextmenu;

import android.os.Bundle;
import android.app.Activity;
import android.view.ContextMenu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ContextMenu.ContextMenuInfo;
import android.widget.TextView;
import android.widget.Toast; public class HelloContextMenuMainActivity extends Activity { private TextView mTextView1 = null; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_hello_context_menu_main); mTextView1 = (TextView) findViewById(R.id.textView1); // 注册要弹出ContextMenu的View
registerForContextMenu(mTextView1); } @Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
// 第二个参数为当前点击的view super.onCreateContextMenu(menu, v, menuInfo); MenuInflater inflater = getMenuInflater();
// 把布局inflate进menu对象
inflater.inflate(R.menu.context_menu1, menu);
} @Override
public boolean onContextItemSelected(MenuItem item) { boolean result = false;
switch (item.getItemId()) {
case R.id.edit: Toast.makeText(HelloContextMenuMainActivity.this, "Edit",
Toast.LENGTH_LONG).show();
result = true;
break;
case R.id.help:
Toast.makeText(HelloContextMenuMainActivity.this, "Help",
Toast.LENGTH_LONG).show();
result = true;
break;
default:
result = super.onContextItemSelected(item);
break; } return result; } }

  Activity的内容布局:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".HelloContextMenuMainActivity" > <TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" /> </LinearLayout>

  Menu的布局:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" > <item
android:id="@+id/edit"
android:showAsAction="ifRoom"
android:title="edit"/>
<item
android:id="@+id/help"
android:title="help"/> </menu>

参考资料

  API Guides: Menus->Creating Contextual Menus

  http://developer.android.com/guide/topics/ui/menus.html#context-menu

最新文章

  1. COGS439. [网络流24题] 软件补丁
  2. CentOS 与 RedHat 关系和区别
  3. 论文第5章:Android绘图平台的实现
  4. NOIP 2014 普及组 T4 子矩阵
  5. 关于Linux系统调用,内核函数【转】
  6. 适合我胃口的angular.js学习资料
  7. C# - DynamicObject with Dynamic
  8. 栈(顺序存储)C++模板实现
  9. 基于 SWTBot 进行 Eclipse GUI 自动化测试
  10. bestcoder单调区间
  11. webapp 开发调试测试方法总结
  12. OpenGL编译问题随手记
  13. RobotFramework下的http接口自动化Get Response header 关键字的使用
  14. python之MySQL MySQLdb 推荐使用姿势,解决中文乱码
  15. luoguP1919 A*B Problem升级版 ntt
  16. Linux用户相关指令
  17. 第 3 章 镜像 - 021 - Docker 镜像小结
  18. Redis注意事项
  19. 深入分析Java Web技术内幕
  20. 图形数据库 Neo4j 开发实战

热门文章

  1. 老鸟谈谈JAVA EE的学习
  2. 记录一个mysql连接慢的问题
  3. HT for Web基于HTML5的图像操作(二)
  4. Socket.Available 属性
  5. MSSQLLocalDB 连接字符串 vs2015
  6. 使用JSLint提高JS代码质量
  7. kendo ui的treeView节点点击事件修改和grid的配置的一点总结
  8. C#单纯的字母数字ASCII码转换
  9. IT技术开发人员获得成功的六大步骤
  10. 一文读懂UGC:互联网上的生态秘密