Gmail-like ListView with checkboxes (and using the ActionBar)

后端 未结 3 1997
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-12-04 13:07

I\'m trying to recreate what Google did with the ListView in the Gmail app. In particular, I would like to have each list item include a CheckBox and two TextViews (one on t

3条回答
  •  囚心锁ツ
    2020-12-04 13:32

    This will work in SDK 7 (android 2.1) and higher. (together with SherlockActionBar)

    Totaly mimic gmail listbox experience.

    I override onTouchEvent so press in the left corner side will activate selection mode; mutch better then trying to click on the tiny cheackbox.

    I override performItemClick so pressing not in the left will act as a Regular press action.

    I override setItemChecked so it will update mActionMode as needed.

    public class SelectListView extends ListView {
    
        private SherlockFragmentActivity mActivity;
        ActionMode mActionMode;
    
          public SelectListView(Context context) {
        this( context, null, 0); 
    }
    
    public SelectListView(Context context, AttributeSet attrs) {   
        this( context, attrs, 0); 
    }   
    
    
    public SelectListView(Context context, AttributeSet attrs, int defStyle) {
        super( context, attrs, defStyle ); 
        setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
        mActivity = (SherlockFragmentActivity) context;
    }
    
        @Override
        public boolean performItemClick(View view, int position, long id) {
            OnItemClickListener mOnItemClickListener = getOnItemClickListener();
            if (mOnItemClickListener != null) {
                playSoundEffect(SoundEffectConstants.CLICK);
                if (view != null)
                    view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
                mOnItemClickListener.onItemClick(this, view, position, id);
                return true;
            }
            return false;
        }
    
        boolean mSelectionMode = false;
        int mStartPosition;
    
        @Override
        public boolean onTouchEvent(MotionEvent ev) {
    
            final int action = ev.getAction();
            final int x = (int) ev.getX();
            final int y = (int) ev.getY();
    
            if (action == MotionEvent.ACTION_DOWN && x < getWidth() / 7) {
                mSelectionMode = true;
                mStartPosition = pointToPosition(x, y);
            }
            if (!mSelectionMode)
                return super.onTouchEvent(ev);
            switch (action) {
            case MotionEvent.ACTION_DOWN:
                break;
            case MotionEvent.ACTION_MOVE:
                if (pointToPosition(x, y) != mStartPosition)
                    mSelectionMode = false;
                break;
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
            default:
                mSelectionMode = false;
                int mItemPosition = pointToPosition(x, y);
                if (mStartPosition != ListView.INVALID_POSITION)
                    setItemChecked(mItemPosition, !isItemChecked(mItemPosition));
            }
    
            return true;
        }
    
        @Override
        public void setItemChecked(int position, boolean value) {
            super.setItemChecked(position, value);
            // boolean r = getAdapter().hasStableIds();
            int checkedCount = getCheckItemIds().length;
    
            if (checkedCount == 0) {
                if (mActionMode != null)
                    mActionMode.finish();
                return;
            }
            if (mActionMode == null)
                mActionMode = mActivity.startActionMode(new ModeCallback());
    
            mActionMode.setTitle(checkedCount + " selected");
    
        }
    
        class ModeCallback implements ActionMode.Callback {
    
            @Override
            public boolean onCreateActionMode(ActionMode mode, Menu menu) {
    
                menu.add(getResources().getString(R.string.aBar_remove)).setIcon(R.drawable.ic_action_trash)
                        .setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
    
                return true;
            }
    
            @Override
            public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
                return true;
            }
    
            @Override
            public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
                Toast.makeText(mActivity, "Delted  items", Toast.LENGTH_SHORT).show();
                mode.finish();
                return true;
            }
    
            @Override
            public void onDestroyActionMode(ActionMode mode) {
                mActionMode = null;
                clearChecked();
            }
    
        }
    
        public void clearChecked() {
            SparseBooleanArray CItem = getCheckedItemPositions();
            for (int i = 0; i < CItem.size(); i++)
                if (CItem.valueAt(i))
                    super.setItemChecked(CItem.keyAt(i), false);
        }
    
    }
    

    you can use any listbox adapter you need.

    if you have a checkbox on your list_item_layout tou need to extent your adapter like this:

    ArrayAdapter mAdapter = new ArrayAdapter(this, R.layout.simple_list_item_multiple_choice,
                R.id.text1, Cheeses.sCheeseStrings) {
    
            @Override
            public View getView(int position, View convertView, ViewGroup parent) {
                View v = super.getView(position, convertView, parent);
                CheckBox checkBox = (CheckBox) v.findViewById(R.id.CheckBox);
                checkBox.setChecked(((ListView)parent).isItemChecked(position));
                return v;
            }
    
        };
    

    Don't forget to use android:background="?attr/activatedBackgroundIndicator" on your list_item_layout.xml

提交回复
热议问题