Android Contextual Action Mode的使用方法

1. 概述

Contextual Action Mode是在Android 3.0开始引入的。floating menu是浮动在view上面,而contextual action mode的菜单项,则显示在Action Bar的一部分区域中。效果如下:


此外,针对ListView、GridView,或其他自定义的AbsListView子类,除了支持单选,还支持多选的行为。

2. 主要步骤

包括如下几个步骤:

  • 创建一个ActionMode.CallBack对象;主要包括:
    • 创建contextual action mode的菜单;
    • 处理action item的选择事件;
  • 对于要显示contextual action mode的View,设置OnLongClickListener等listener,其主要目的在于:
    • 调用Activity或Fragment的startActionMode()方法启用action mode;

3. 示例

本节以一个EditText控件为例来说明contextual action mode的使用方法。这个例子,和Android官网的说明完全一致。对应位置:sdk/docs/guide/topics/ui/menus.html


3.1 菜单资源

<?xml version="1.0" encoding="utf-8"?>

<!-- context_menu.xml -->
<menu xmlns:android="http://schemas.android.com/apk/res/android" >

    <item
        android:id="@+id/first_context_menu_item"
        android:title="@string/first_context_menu_item"
        android:icon="@drawable/ic_launcher"
        android:titleCondensed="@string/first"
        android:showAsAction="ifRoom|withText"/>
    <item
        android:id="@+id/second_context_menu_item"
        android:title="@string/second_context_menu_item"
        android:icon="@drawable/ic_launcher"
        android:titleCondensed="@string/second"
        android:showAsAction="ifRoom|withText"/>

</menu>

3.2 字符串资源

<string name="first_context_menu_item">first item</string>
<string name="second_context_menu_item">second item</string>
<string name="first">first</string>
<string name="second">second</string>

3.3 Java代码

package com.example.hellocontextualactions;

import android.app.Activity;
import android.os.Bundle;
import android.view.ActionMode;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnLongClickListener;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends Activity {
	//private static final String TAG = "MainActivity";
	private EditText editText = null;
	
	private ActionMode actionMode = null;
	
	private ActionMode.Callback actionModeCallBack = new ActionMode.Callback() {
		@Override
		public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
			return false;
		}

		@Override
		public void onDestroyActionMode(ActionMode mode) {
			actionMode = null;
		}

		@Override
		public boolean onCreateActionMode(ActionMode mode, Menu menu) {
			MenuInflater inflater = mode.getMenuInflater();
			inflater.inflate(R.menu.context_menu, menu);
			return true;
		}

		@Override
		public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
			switch (item.getItemId()) {
			case R.id.first_context_menu_item:
				Toast.makeText(getApplicationContext(), 
						"first context menu item clicked.",
						Toast.LENGTH_SHORT)
						.show();
				
				mode.finish();
				return true;

			case R.id.second_context_menu_item:
				Toast.makeText(getApplicationContext(), 
						"second context menu item clicked.",
						Toast.LENGTH_SHORT)
						.show();
				mode.finish();
				return true;

			default:
				return false;
			}

		}
		
	};

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		setContentView(R.layout.hello_contextual_actions);

		editText = (EditText) this.findViewById(R.id.edit_text_id);
		editText.setText("Hello, Contextual Actions!");
		editText.setOnLongClickListener(new OnLongClickListener() {

			@Override
			public boolean onLongClick(View v) {
				if (actionMode != null) {
					return false;
				}

				actionMode = startActionMode(actionModeCallBack);
				return true;
			}
			
		});
	}

}

3.4 运行效果

应用启动后的界面:


长按EditText控件后,进入action mode,会在action bar上面显示ActionMode.CallBack对象中创建的菜单所包括的action items:


当按了Action Bar左边的Done(勾号)之后,会退出action mode。


选择了某一个action后的效果:


4. 代码解读

4.1 OnLongClickListener

在contextual action mode使用方式下,是由每个View去设置OnLongClickListener对象,用于侦听long click事件。而long click也是用来生成floating context menu或进入contextual aciton mode的时机。

——在floating context menu中,是直接通过重载Activity或Fragment的onCreateContextMenu()来生成菜单。由此可以看到两者上下文菜单的实现方式上的差异。

需要注意的是,对于ListView、GridView,或者其他继承自AbsListView的子类来讲,这些对象没法侦听到long click事件。因为在这些视图中,我们可以click的是一个个的item元素。为此,AbsListView提供了OnItemLongClickListener接口。——此外还有多选的接口,后面再展开讨论。


在OnLongClickListener或OnItemLongClickListener等实现中,需要调用Activity或Fragment的startActionMode(CallBack)来启动action mode。进而在Action Bar上面显示CallBack生成的菜单资源,即所谓的menu actions。


4.2 CallBack

CallBack中的方法,和onCreateContextMenu()、onContextItemSelected()等方法类似,包括了创建菜单、处理选中事件等。这一点通过方法名称、以及代码示例即可理解。


4.3 多个View的处理

如果在一个Activity(UI视图)上有多个View对象都要支持contextual action mode怎么办呢?

  • 此时可以在CallBack对象中生成所有的菜单资源,并在onPrepareActionMode()中设置各个action(或称menu item)的显示状态;
  • 也可以为每个View对象创建各自的CallBack实现;
  • 其他的方式,比如在Activity范围内记录当前所选择的view对象,从而在CallBack中据此创建不同的菜单

4.4 ActionMode的setTitle()方法

调用ActionMode的setTitle()或setSubTitle()方法,可以在Action Mode下面,在Action Bar上显示一些字符串,给用户呈现一些信息。为此,我们对前面的代码做一点修改,如下:

@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
	switch (item.getItemId()) {
	case R.id.first_context_menu_item:
		Toast.makeText(getApplicationContext(), 
				"first context menu item clicked.",
				Toast.LENGTH_SHORT)
				.show();
		
		//mode.finish();
		mode.setTitle("first context menu item clicked.");
		mode.setSubtitle("first subtitle");
		return true;

	case R.id.second_context_menu_item:
		Toast.makeText(getApplicationContext(), 
				"second context menu item clicked.",
				Toast.LENGTH_SHORT)
				.show();
		//mode.finish();
		mode.setTitle("second context menu item clicked.");
		mode.setSubtitle("second subtitle");
		return true;

	default:
		return false;
	}

}

即我们只通过Back或Done action来关闭action mode,同时选择了某个action item之后,在action bar显示一些信息。效果如下:




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值