0

basically, I have a ListView in my android application. I want it to be possible for the user to select multiple rows by clicking on them. To implement this, I've made a class that implements onItemClickListener, and the ListView sets this as the OnItemClick Listener.

This is the code in the listener:

public void onItemClick(AdapterView<?> parentAdapterView, View viewSelected, int pos, long id) {
    if(selectedItems.contains(viewSelected)) {
        //remove it from the selected list.
        selectedItems.remove(viewSelected);
        viewSelected.setBackgroundColor(Color.BLACK);
    }
    else {
        selectedItems.add(viewSelected);
        viewSelected.setBackgroundColor(Color.RED);
    }
}

The selectedItems is simply a List of Views (List), that I used to keep track of all the items that have been selected.

This works fine until the number of items causes the list to overflow (and thus, the list becomes scrollable). Then, when one item is clicked, another item is highlighted (in addition to the first) further down the list?

Can't think why this would be happening? I've searched around on Google, but to no avail...

I'd be grateful for any help on the matter.

Cheers

Edit: The code that I used to provide the views for list view is simply:

uiListViewRes = R.layout.main_list_item;
ListView overTwoDaysView = (ListView) findViewById(R.id.overtwolistview);

String[] from = {"_id","foodItemName", "expire", "dateAdded"};
int[] to = {R.id.itemIDhidden,R.id.name, R.id.expiry, R.id.dateAddedLabel};

SimpleAdapter overTwoDaysAdapter = new SimpleAdapter(this, adapter.getAllItemsOverTwoDays(), uiListViewRes, from, to);

overTwoDaysView.setAdapter(overTwoDaysAdapter);
Swift Sharp
  • 2,604
  • 3
  • 30
  • 54
  • Please post your get view method, I think the trouble lies there. – R.daneel.olivaw Jan 04 '12 at 17:49
  • When you say get view method, I don't quite understand. My code for obtaining the ListView is simply: ListView overTwoDaysView = (ListView) findViewById(R.id.overtwolistview); the code for setting the adapter is: SimpleAdapter overTwoDaysAdapter = new SimpleAdapter(this, adapter.getAllItemsOverTwoDays(), uiListViewRes, from, to); overTwoDaysView.setAdapter(overTwoDaysAdapter); and the code where I set the listener is: overTwoDaysView.setOnItemClickListener(listener); Sorry if the formatting on this comment is awful! I've only just started using this website. – user1130481 Jan 04 '12 at 19:03

3 Answers3

0

What happens if you use this.invalidate();

Not sure it will work, it seems like you're doing everything right... Redrawing might help.

public void onItemClick(AdapterView<?> parentAdapterView, View viewSelected, int pos, long id) {
    if(selectedItems.contains(viewSelected)) {
        //remove it from the selected list.
        selectedItems.remove(viewSelected);
        viewSelected.setBackgroundColor(Color.BLACK);
    }
    else {
        selectedItems.add(viewSelected);
        viewSelected.setBackgroundColor(Color.RED);
    }
    this.invalidate();
}

If you're reusing the view every time the problem could lie there but this is the only thing I can think about in this code.

J. Maes
  • 6,862
  • 5
  • 27
  • 33
  • Thanks for your suggestion, I tried this and it still didn't work. From starting the app from scratch, then just clicking the top row, the top row highlights, and so does another one further down. Then if I click the row further down, both are deselected. It's as though the viewSelected variable references both rows, is that even possible? Cheers – user1130481 Jan 04 '12 at 20:19
  • How do you provide the views for the ListView? Is it through an Adapter? If so, could you post the code or otherwise the code you use to generate the views for the ListView. – J. Maes Jan 04 '12 at 20:58
  • Okay, I've been messing around with it some more. If I click an item near the top of the list, another one is also highlighted further down (as mentioned before). I've also noticed that if I scroll up and down the list repeatedly, this selection has a habit of changing (seems random), so it will change to unhighlighted, then back to highlighted again. Sometimes another row entirely will be highlighted. It is truely bizare, can anyone offer me any suggestions/advice? Cheers – user1130481 Jan 04 '12 at 21:04
  • One way or another, it has to be the same view or referencing to the same view. Could you post the code where you create the views and assign them to the listview? – J. Maes Jan 04 '12 at 21:14
  • Hi, sorry missed your previous post, have updated the Question to show how I get the view (for each row, yes?), and assign if it that's what you mean. I also tried using 'parentAdapterView.getChildAt(pos).setBackgroundColor(Color.RED);', but it still does the same thing, so it seems that even calling getChildAt(), with a specified position still affects multiple rows, very strange... – user1130481 Jan 04 '12 at 21:23
  • Sorry to seem like a pest! Using `parentAdapterView.getChildCount()` seems to return a maximum of 5 every time, despire there clearly being more than 5 in the list? Bizare, any suggestions as to where I might be going wrong? Thanks again – user1130481 Jan 04 '12 at 21:58
0

The problem is that ListView reuses Views for better performance.

So ListView allocates only X number of Views and then tries to reuse the not visible ones - by changing the properties of the View.

That means that you can't save the Views/set the background of the Views because that same View instance will be used later in the ListView.


There are several approaches to solve this problem:

  1. You can have a look at the ListView's CHOICE_MODE_MULTIPLE

    listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
    

    Example: http://www.vogella.de/articles/AndroidListView/article.html

  2. You can save the ID or position of the row and use it in a custom Adapter to set the background accordingly.

balazsbalazs
  • 4,071
  • 1
  • 24
  • 29
  • Thanks for the info mate! I was beginning to think the same thing when I noticed that the AdapterView.getChildCount() returned a number that was smaller that the number of items in the list. I'll have a look into your recommendations. Cheers! – user1130481 Jan 04 '12 at 22:10
  • Yes, sorry have only just seen this! Thanks again for your help! – user1130481 Feb 24 '12 at 18:40
0

I think I see the problem now, as you are using the default implementation of the simple adapter the states of the check boxes are not maintained.

The below response defines a custom adapter which will maintain the states of individual list item,

Custom Adapter

Community
  • 1
  • 1
R.daneel.olivaw
  • 2,681
  • 21
  • 31