0

When I click a list item, every 12th item is also selected. ListViews recycle views and therefore many items are being selected, any idea how I overcome the problem so just the items I click are marked as checked.

@Override
public void onListItemClick(ListView l, View v, int position, long id){

    CheckedTextView check = (CheckedTextView) v;

    if (check.isChecked()){
        check.setChecked(false);
        selections.remove((Integer) position);
    }
    else{
        check.setChecked(true);
        selections.add((Integer) position);
    }
}

I use an ArrayAdapter. Names is a String[] of about 1000 options.

adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_multiple_choice, names);
setListAdapter(adapter);
Allan Macmillan
  • 1,481
  • 3
  • 18
  • 30

2 Answers2

1

In lisview, recycling is very tricky concept, first by recycled view android means view which were used earlier, so basically this view will contain all the parameter which you or user set earlier.

This view is now returned to your adapter, what you do is to check if its null inflate a new view set new values supply it back, if its not then refresh the widgets view contains with new values and then supply it back.

Now coming back to your code, you are simply checking if this view was checked or not, say suppose you checked first view in you list, now when you scroll down further this same view will be returned to you through recycling and guess what it will be checked again, remember it was the same first view you used, this is reason for your problem for founding a unchecked view checked.

Now to your resolution, maintain a separate list somewhere globally to hold on checked index, and from your adapter just check or uncheck the checkbox before sending it to list depending about its index presence in maintained list. this will resolve your probelm.

Please try something like this.

-- Have a static HashMap on your main activity.

--Implement two methods over you activity, AddSelection and RemoveSelection

--On your adapter, implement onCheckedStateChanged listener and, perform either addition or deletion from the map, based on position in list.

In Your Activity:

  private static HashMap<Integer,Integer> selectedPositions = new HashMap<Integer,Integer>();
    public static boolean isSelected(int position){
        System.out.println("#### Position: " + position + " Value: " + selectedPositions.containsKey(position));
        return selectedPositions.containsKey(position);
    }

    public static void addSelection(int position){
        System.out.println("#### Puttin Position: " + position);
        selectedPositions.put(position,position);
    }

public static void removeSelection(int position){
    System.out.println("#### Removing Position: " + position);
    selectedPositions.remove(position);
}

In your adapter:

checkbox.setChecked(MainActivity.isSelected(position));

checkbox.setOnCheckedChangeListener(new OnCheckedChangeListener(){

    @Override
    public void onCheckedChanged(CompoundButton view, boolean state) {
        // TODO Auto-generated method stub
        if(state == true){
            MainActivity.addSelection(position);
        }else{
            MainActivity.removeSelection(position);
        }
    }

});

thats it now, whenever you want iterate through the hasmap for finding out selected items, make sure you clear it when job is done, else u will end up piling selected positions again and again.

Techfist
  • 4,314
  • 6
  • 22
  • 32
1

As this answer CheckBox in ListView says maintain a list of your checked items and then check your CheckBox in getView based on that list.

Also set the onCheckedChangeListener for that CheckBox null before checking it or else the corresponding listener will be called.

Community
  • 1
  • 1
Apoorv
  • 13,470
  • 4
  • 27
  • 33