天天看点

Listview使用CHOICE_MODE_MULTIPLE_MODAL实现多选模式

(参考博客: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菜单可以实现“全选”和“全不选”的功能。

Listview使用CHOICE_MODE_MULTIPLE_MODAL实现多选模式

代码如下:

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>