Question

Android and Java noob here, although I've dabbled in various languages over the years. This has been driving me bonkers all week.

Trying to write my first app, and it's the clichéd shopping list app, with a ListView made up of CheckedTextView items (as supplied by android.R.layout.simple_list_item_multiple_choice). The ListView is set to CHOICE_MODE_MULTIPLE.

The backend to the ListView is an ArrayList, called shoppingItems, where ShoppingListItem is simply defined as:

public class ShoppingListItem {

    public String name;
    public Boolean checked;

    // The obvious constructors here...

}

and I have an ArrayAdapter with an over-ridden getView() method:

shoppingListAdapter = new ArrayAdapter<ShoppingListItem>
                        (this,
                        android.R.layout.simple_list_item_multiple_choice,
                        android.R.id.text1,
                        shoppingItems)
{
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        CheckedTextView rowView = (CheckedTextView)convertView;

        if (rowView==null){
            LayoutInflater inflater = getLayoutInflater();
            rowView = (CheckedTextView)inflater.inflate(android.R.layout.simple_list_item_multiple_choice, parent, false);
        }               
        rowView.setText(shoppingItems.get(position).name);
        rowView.setChecked(shoppingItems.get(position).checked);
        return rowView;
    }
};

Everything works fine -- adding items, editing items, removing an individual item via its context menu -- except removing all the checked items via a "Remove" button at the bottom of the screen.

I must have tried writing my removeCheckedItems method half a dozen different ways, including various combinations of:

  • removing checked items using the list adapter (which from all I've read is the way that's supposed to work)
  • removing checked items directly from the ArrayList, then calling notifyDatasetChanged()
  • explicitly removing child views from the ListView
  • iterating over the results of the ListView's getCheckedItemPositions(), rather than the whole list

Here's my most naive attempt:

private void removeCheckedItems(){

    ShoppingListItem item;
    for (int i=0; i< adapter.getCount(); i++) {
        item = shoppingListAdapter.getItem(i);
        if (shoppingListView.isItemChecked(i)){
            item = shoppingItems.get(i);
            shoppingListAdapter.remove(item);
        }
    }
    removeBtn.setEnabled(false);
}

However I do it, though: the checkboxes in the ListView just don't stay in sync with the data in the ShoppingItems ArrayList. Specifically, if I start off with:

Item one   [ ]
Item two   [ ]
Item three [ ]

in the list, then check Item one:

Item one   [x]
Item two   [ ]
Item three [ ]

then click my Remove button, which confirms the action via a popup dialog, the first item disappears, but the checkbox in the first row remains checked:

Item two   [x]
Item three [ ]

At this point, I know by means of debugging messages etc. that the contents of the ArrayList are correct -- i.e. that it contains two ShoppingListItem items with the correct names, both of whose 'checked' fields are set to false.

I'm sure I'm missing something obvious, but despite reading numerous examples, and even more ListView-related answers on here, I can't see it for the life of me. (Complete code listing for the activity as it currently stands can be found here, if you need to see more.)

Was it helpful?

Solution 2

For the record, the only way I ever got this to work in the end was to use my own custom row layout and inflate that in getView(), rather than using android.R.layout.simple_list_item_multiple_choice. Everything worked just the way I'd expected it to all along when I did that, including the ListView updating instantly and correctly whenever I changed the data via the ArrayAdapter, and notifyDatasetChanged() doing likewise when I was changing the data directly.

OTHER TIPS

You just need to call the fillData() method again from your removeCheckedItems method.

Everytime you make a change to the data, you need to "fill" the data for the list again, refresh the list adapter.

Do a Google Search for 'ListActivity fillData' tutorial, and you get lots of great examples.

Here are a couple good ones:

Let me know if you get stuck, I'll be able to help more tomorrow. I've done this a lot, so I can help you work the kinks out of it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top