(參考部落格: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()== && 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= ; 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>