(参考博客:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1105/1906.html)
ListView 使用CHOICE_MODE_MULTIPLE_MODAL进入多选模式的实现:界面很简单,有一个简单的显示文本的容器以及一个checkbox。
实现的功能为:长按进入多选模式,进入多选模式后长按item、点击item、点击checkbox都可以实现选中和不选中的切换,同时在多选模式下如果当前选中item的个数为0,也不会退出多选模式;同时可以通过手机系统的返回键回到普通模式;在普通模式下点击item则弹出文本内容;普通模式下长按item再次进入多选模式;在多选模式下的menu菜单可以实现“全选”和“全不选”的功能。
代码如下:
public class MessageListAdpter extends CursorAdapter {
private Activity mActivity;
private ListView mMessageList;
private ModeCallback mCallback;
private boolean mIsMultipleChoiceMode;
public MessageListAdpter(ListView listview,Activity activity, Cursor c) {
super(activity, c);
mActivity = activity;
mFactory = LayoutInflater.from(activity);
mMessageList = listview;
mCallback = new ModeCallback();
mMessageList.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
mMessageList.setMultiChoiceModeListener(mCallback);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
View view = mFactory.inflate(R.layout.message_list_item, parent, false);
return view;
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
//显示文本内容的部分省略
setOnClick(view,messageItem,cursor.getPosition());
displayChecked(view,cursor.getPosition());
}
private void displayChecked(View view,final int position) {
Log.d(TAG,"displayChecked()执行.....position:"+position);
final CheckBox cbChecked = (CheckBox)view.findViewById(R.id.cb_check);
cbChecked.setOnCheckedChangeListener(null);//这里需要先清除
if(mIsMultipleChoiceMode){
cbChecked.setVisibility(View.VISIBLE);
if(mMessageList.isItemChecked(position)){
cbChecked.setChecked(true);
}else{
cbChecked.setChecked(false);
}
}else{
cbChecked.setVisibility(View.GONE);
}
cbChecked.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
Log.d(TAG,"checkbox点击.....position:"+position);
//mMessageList.setItemChecked(position,isChecked);
changeChecked(position);
}
});
public void setOnClick(View view,final MessageItem messageItem,final int position){
//view.setTag(R.id.tag_message_list_item_position,position);
view.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
Log.d(TAG,"item 长按点击.....position:"+position);
if(mIsMultipleChoiceMode){
//如果当前是在多选模式则长按直接改变该处item的选中状态
//mMessageList.setItemChecked(position,!mMessageList.isItemChecked(position));
changeChecked(position);
}else{
//如果当前不是在多选模式,则长按需要切换为多选模式
mMessageList.setItemChecked(position,true);
//mMessageList.clearChoices();//不需要清除选中,因为当前长按的这个item需要被选中
//mCallback.updateSeletedCount();
}
return true;
}
});
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//int position = (Integer) v.getTag(R.id.tag_message_list_item_position);
Log.d(TAG,"item 点击.....position:"+position);
if(mIsMultipleChoiceMode){
//如果当前处于多选模式,则单击item需要切换该处item的选中状态
//mMessageList.setItemChecked(position,!mMessageList.isItemChecked(position));
changeChecked(position);
}else{
//如果当前不处于多选模式,则单击直接弹出item的短信内容
Toast.makeText(mActivity,messageItem.getBody(),Toast.LENGTH_SHORT).show();
}
return;
}
});
}
public void changeChecked(int position){
//SparseBooleanArray checkedItemPositions = mMessageList.getCheckedItemPositions();
//在主动调用若干次mMessageList.setItemChecked(position,false)后,如果此时选中item的个数为0,则listview会自动将多选模式切换为普通模式,
// 因此这里需要做这个判断:如果当前不需要选中某一个item后就选中的item总数是0,就直接调用判断里面的方法保持在多选模式
if(mMessageList.getCheckedItemCount()==1 && mMessageList.isItemChecked(position)){
unSelectedAll();
notifyDataSetChanged();
}else{
mMessageList.setItemChecked(position,!mMessageList.isItemChecked(position));
}
mCallback.updateSeletedCount();
}
private class ModeCallback implements ListView.MultiChoiceModeListener {
private View mMultiSelectActionBarView;
private TextView mSelectedCount;
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
mIsMultipleChoiceMode = true;
Log.d(TAG,"onCreateActionMode()执行......");
// actionmode的菜单处理
MenuInflater inflater = mActivity.getMenuInflater();
inflater.inflate(R.menu.multi_select_menu, menu);
if (mMultiSelectActionBarView == null) {
mMultiSelectActionBarView = LayoutInflater.from(mActivity)
.inflate(R.layout.list_multi_select_actionbar, null);
mSelectedCount =
(TextView)mMultiSelectActionBarView.findViewById(R.id.selected_conv_count);
}
mode.setCustomView(mMultiSelectActionBarView);
((TextView)mMultiSelectActionBarView.findViewById(R.id.title)).setText("已选择:");
return true;
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
Log.d(TAG,"onPrepareActionMode()执行......");
//更新菜单的状态
MenuItem mItem = menu.findItem(R.id.action_slelect);
if(mMessageList.getCheckedItemCount() == getCount()){
mItem.setTitle("全不选");
}else{
mItem.setTitle("全选");
}
return true;
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
Log.d(TAG,"onActionItemClicked()执行......");
switch (item.getItemId()) {
case R.id.action_slelect:
if(mMessageList.getCheckedItemCount() == getCount()){
unSelectedAll();
}else{
selectedAll();
}
notifyDataSetChanged();
break;
default:
break;
}
return true;
}
@Override
public void onDestroyActionMode(ActionMode mode) {
mIsMultipleChoiceMode = false;
Log.d(TAG,"onDestroyActionMode()执行......");
mMessageList.clearChoices();
}
@Override
public void onItemCheckedStateChanged(ActionMode mode,
int position, long id, boolean checked) {
Log.d(TAG,"onItemCheckedStateChanged()执行......");
Log.d(TAG,"mMessageList.getCheckedItemCount():"+mMessageList.getCheckedItemCount());
mode.invalidate();
updateSeletedCount();
notifyDataSetChanged();
}
public void updateSeletedCount(){
mSelectedCount.setText(Integer.toString(mMessageList.getCheckedItemCount()));
}
}
public void selectedAll(){
for(int i= 0; i< getCount(); i++){
mMessageList.setItemChecked(i, true);
}
mCallback.updateSeletedCount();
}
public void unSelectedAll(){
mMessageList.clearChoices();
mCallback.updateSeletedCount();
}
}
R.layout.list_multi_select_actionbar文件:
<LinearLayout
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">
<TextView
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" />
<TextView
android:id="@+id/selected_conv_count"
android:maxLines="1"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="#ccffffff"
android:layout_gravity="center_vertical"
android:paddingRight="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
R.menu.multi_select_menu:
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/action_slelect"
android:orderInCategory="100"
android:showAsAction="never|withText"
android:title="@string/action_settings"/>
</menu>