Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
160 views
in Technique[技术] by (71.8m points)

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

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 top of the other). I need listeners for when the CheckBox is checked (or clicked) and when anywhere else on the list item is clicked. Lastly, I'd like the ActionBar to reflect that items are selected and provide options like Select All, Select None, etc (see this screenshot).

enter image description here

So far, here's the layout I came up with.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" >

    <CheckBox android:id="@+id/checkBox"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical|center_horizontal" />

    <LinearLayout android:id="@+id/linearLayout1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="6dp"
        android:focusable="true"
        android:clickable="true" >

        <TextView android:id="@+id/titleTextView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="16sp" />

        <TextView android:id="@+id/dateTextView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="12sp" />

    </LinearLayout>

</LinearLayout>

This displays everything properly, but I need pointers on how to set up the listeners for the two Views (@+id/checkBox and @+id/linearLayout1). I have looked at the List16 API demo, but they're using the simple_list_item_activated_1 layout and I'm not sure what the XML for that looks like. As their code suggests, I created a ModeCallback class that implements ListView.MultiChoiceModeListener and I set the ListView's choice mode to CHOICE_MODE_MULTIPLE_MODAL, but I don't know how to get the CheckBox in my layout to work with this.

Has anyone successfully copied the Gmail app's ListView behavior? I've searched quite a bit and could not come up with anything (despite several others asking similar questions, like this one - most answers just point back to this same API demo).

Also, for context, I'm loading data from a SQLite database into the list and I've created my own Cursor adapter (which works fine). I have a feeling I need to set up listeners in this class in the newView() and bindView() methods, but everything I've tried hasn't worked.

Any ideas?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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<String> mAdapter = new ArrayAdapter<String>(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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...