一般来说,在安卓应用中listview的多选操作都是和ActionMode结合起来的。ActionMode可以理解为actionbar的另一种形式,同样可以在菜单中添加动作项,同样可以通过setCustomView自定义标题栏,并且当启动ActionMode之后,它所占据的位置是和actionbar重叠的。使用ActionMode的好处是可以在同一个activity中完成多选操作,且切换成新的视图时,切换的整个过程非常自然,并且ActionMode有自己的回调方法。其实ActionMode仅仅是一种视觉上的实现,多选的功能和ActionMode本身一点关系都没有。actionbar和ActionMode我理解为在一个activity中的两种模式,不同的模式下做不同的操作。

ActionMode最典型的例子是android4.0上邮件应用和mms应用。当你查看一个邮件列表或者查看短信列表的时候,长按一个item,将会进入ActionMode模式。

下面我用图片展示一下actionbar和ActionMode模式。

图1:正常情况下记事本的列表界面是这样的:图2:当我选择多选进入ActionMode之后:

Android 多級选择器组件_android多媒体开发笔记 2

Android 多級选择器组件_android多媒体开发笔记 2_02

关于actionmode最基本的用法请看这篇文章:安卓中的上下文操作模式ActionMode

我也是看了这篇文章之后,仿照着写出来的,但是直接这样写编程的时候会出现一些问题 。当我点击一个记事的时候,右图右上角的数字应该相应变化,但是在activity里面实现actionmode接口的却是一个内部类:

private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() {
// Called when the action mode is created; startActionMode() was called
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
// Inflate a menu resource providing context menu items
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.context_menu, menu);
return true;
}
// Called each time the action mode is shown. Always called after onCreateActionMode, but
// may be called multiple times if the mode is invalidated.
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false; // Return false if nothing is done
}
// Called when the user selects a contextual menu item
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_share:
shareCurrentItem();
mode.finish(); // Action picked, so close the CAB
return true;
default:
return false;
}
}
// Called when the user exits the action mode
@Override
public void onDestroyActionMode(ActionMode mode) {
mActionMode = null;
}
};

在activity中没法直接操作里面的视图。因此我换一种写法,让activity实现这个接口,那么actionmode的视图就能在activity中随意的操作了。

extends Activity implements OnClickListener,ActionMode.Callback
然后在启动actionmode的时候,这个回调对象就是activity自己:} else if (view == mMenuAction) {当点击多选按钮//
if (mActionMode != null) {
return ;
}
// Start the CAB using the ActionMode.Callback defined above
mActionMode = startActionMode(this);
......
}

Activit实现ActionMode最重要的回调方法是onCreateActionMode,在这个方法中,我将标题栏设置成自定义的视图,视图的布局在layout目录下的xml文件中。

xml文件如下:

xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/custom_title_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
android:id="@+id/title"
android:maxLines="1"
android:singleLine="true"
android:layout_gravity="center_vertical"
android:layout_centerVertical="true"
android:textAppearance="?android:attr/textAppearanceMediumInverse"
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
android:id="@+id/selected_count"
android:maxLines="1"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceLarge"
android:layout_gravity="center_vertical"
android:paddingRight="10dip"
android:textColor="#FFFFFF"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />

然后在activity@Override

public boolean onCreateActionMode(ActionMode mode, Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.note_list_action_options, menu);
mSelectAndDelete= menu.findItem(R.id.delete);
if (mMultiSelectActionBarView == null) {
mMultiSelectActionBarView = LayoutInflater.from(PenNoteActivity.this)
.inflate(R.layout.list_multi_select_action, null);
mSelectedConvCount =
(TextView)mMultiSelectActionBarView.findViewById(R.id.selected_count);
}
mode.setCustomView(mMultiSelectActionBarView);
((TextView)mMultiSelectActionBarView.findViewById(R.id.title))
.setText(R.string.multi_select);
mSelectedConvCount.setText("0");
return true;
}

其中mode.setCustomView(mMultiSelectActionBarView);一行就是将标题栏设置成自定义布局。

按照上面的代码执行之后,我们就得到了图2最上面的效果,但是你应该注意到图2和图1的不同之处还有下面部分。下面是动作项,具体的定义是在menu里面,如果要在actionmode中采用某个menu,需要在onCreateActionMode中这样做:

MenuInflater inflater = getMenuInflater();