天天看點

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>