views:

1016

answers:

2

Hi guys,

My scenario:
-I'm using a list view in multiple choice mode to enable a user to delete several items he/she has checked, at once.
-When the user clicks the delete button, i do the following:
-get positions of checked items using: myList.getCheckedItemPositions();
-Get the items in this position and put them to a list - toDeleteList.
-(QUESTION BASED ON THIS STEP) use myList.setItemChecked(position, false) to uncheck the list item.
-Remove the items in the "toDeleteList"

Now, i was "forced" to manually uncheck the list item because the result of myList.getCheckedItemPositions() does not change after deleting from mylist.. i.e

-if, for example, I delete the 1st item (a) of list [a, b, c, d], b will appear checked after the delete ie. in list the list [b, c, d] - after deleting a.

Question is why? Because the SparseBooleanArray returned by myList.getCheckedItemPositions(); is the same before and after deleting from the list - using the adapter.

I thought (i could be wrong) that after removing an item from the list via the adapter, the CheckedItemPositions array should also change to reflect the new state of the list

eg. - mylist = [a, b, c, d]
- then i check items at position 0 and 3 checked (a & d)
- the checked item positions (mylist.getCheckedItemPositions()) array now has values true for positions 0 and 3
- If i remove a & d from the list, therefore, mylist = [b,c], mylist.getCheckedItemPositions() is still the same as above ie. positions 0 and 3 are still checked after deleting items from the list (i think this is not normal - but again i could be wrong)
-I was expecting it not to be checked for positions 0 & 3 because the items that were previously at these positions are no longer in the list.

i'm i getting something wrong here (or having the wrong expectations :) ) ? someone please clarify this..
Thanks in advance,

+1  A: 

Speaking out my personal opinion, I am assuming the positions would still remain checked because the getCheckedItemPositions() reflects the positions opposed to values, so if positions 0 and 3 are still exist inside the ListView after deletion, they will remain checked.

I could be wrong, just voicing my own opinion. Good luck

Anthony Forloney
Thanks.. i see what you mean but i thought if i use mylist.getCheckedItemPositions() on the new list, ie. with previously checked items no longer in the list (after using adapter.remove()..)- the result should be empty/null because my list no longer contains checked items.. - again maybe you're right, thanks
cire
+2  A: 

I was struggling with this same issue and this is what worked for me.

First I've set a cursor adapter that keeps the items checked state based on their ids, since positions aren't useful when the list can be changed dynamically.

private class TagListAdapter extends SimpleCursorAdapter {
    /**
     * Stores boolean values for the list items, based on their ids.
     */
    SparseBooleanArray mCheckStates;

    public TagListAdapter(Context context, int layout, Cursor c, String[] from, int[] to) {
        super(context, layout, c, from, to);
        mCheckStates = new SparseBooleanArray();
    }

    /**
     * Sets an id as checked/unchecked.
     * @param id
     * @param checked
     */
    public void setChecked(int id, boolean checked) {
        mCheckStates.put(id, checked);
    }

    /**
     * @see android.widget.ListAdapter#getView(int, View, ViewGroup)
     */
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View view = super.getView(position, convertView, parent);

        if(!mCursor.moveToPosition(position)) {
            throw new IllegalStateException("couldn't move cursor to position " + position);
        }

        int id = mCursor.getInt(INDEX_OF_COLUMN_ID);
        if(mCheckStates.indexOfKey(id) < 0) {
            // Populate checked value for the first time.
            mCheckStates.put(id, function_that_returns_if_the_item_is_checked(id));
        }

        // Set the item as checked or unchecked based on the value stored in mCheckStates.
        mListView.setItemChecked(position, mCheckStates.get(id, false));
        return view;
    }
}

Then in my activity I've set a onListItemClick() that executes the related check/uncheck action and sets the checked state in the adapter:

@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
    super.onListItemClick(l, v, position, id);
    boolean checked = ((CheckedTextView) v).isChecked();

    if(checked == true) {
        // execute uncheck related action
        function_called_when_item_is_unchecked(id);
    } else {
        // execute check related action
        function_called_when_item_is_checked(id);
    }

    // Check/uncheck the item in the adapter.
    ((TagListAdapter) getListAdapter()).setChecked((int) id, !checked);
}
moraes