mixkat
mixkat

Reputation: 3785

Custom listview with checkbox problem

I'm trying to create a custom list which will have checkboxes that allow you to select several items from the list.

The list with the checkboxes is displayed ok but if i check a checkbox and then scroll other items further down the list are also checked.

Its basically the same problem as here

I understand that it has something to do with the way android recycles the view but I cant see how to fix this! Can somebody help me???

Thanks -- Mike

Upvotes: 6

Views: 4706

Answers (4)

Jimit Patel
Jimit Patel

Reputation: 4297

Check the code below -

public View getView(int position, View convertView, ViewGroup parent){
            View view = convertView;
            ViewHolder holder = new ViewHolder();

            if(view == null){

                view = inflater.inflate(R.layout.list_callcycle_blue, null);                
                holder.llContainer = (LinearLayout) view.findViewById(R.id.ll_container);
                holder.lblLabel = (TextView) view.findViewById(R.id.txt_desc);
                holder.cb = (CheckBox) view.findViewById(R.id.cb_store);

                view.setTag(holder);
            } else {
                holder = (ViewHolder) view.getTag();
            }

            final Object data = getItem(position);
            holder.lblLabel.setText(data.getDescription());

            holder.cb.setTag(position);
            holder.cb.setOnCheckedChangeListener(new OnCheckedChangeListener() {

                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

                    int position = (Integer) buttonView.getTag();
                    objects.get(position).setChecked(buttonView.isChecked());
                }
            });
            holder.cb.setChecked(isChecked(position));

            return view;
        }

Always keep in mind, use change holder.cb.setOnCheckedChangeListener() i.e. any listener before it's setting data, in our case it is holder.cb.setChecked()

Reason : When we scroll, listview will recycle the views, so if setchecked is used before listeners then it will pick values on the basis of old listener. And if we set it after listener, then it will take latest values

EDITED PART Below part will show how isChecked() and setChecked() methods used for retrieving checked data

/*
 * This function is in your Custom Adapter Class
 */
private boolean isChecked(int position){
    return object(position).isChecked();
}


/**
 * Getter Setter Class / Data Model Class that defines your object
 */
private class MyObject{
    private boolean isChecked;
    private String a, b, c, orWhateverYourObjectNeeds;

    public void setChecked(boolean isChecked){
        this.isChecked = isChecked;
    }

    public boolean isChecked(){
        return isChecked
    }
}

Upvotes: 0

iluu
iluu

Reputation: 406

You could try implementing OnClickListener for checkbox instead of OnCheckChangedListener. It worked for me.

Upvotes: 2

james
james

Reputation: 26271

Create an ArrayList<Integer>. add a OnCheckChangedListener to your checkbox. Inside the changed method, add or remove the list view position to the ArrayList<Integer>.

in your getView method, check to see if the ArrayList<Integer> contains the current list view position. if it contains the position, set checked to true, otherwise false.

every time you click a checkbox, either add or remove the Integer from the ArrayList.

Upvotes: 0

Matthew
Matthew

Reputation: 44919

You need a data structure to keep track of which rows are checked. This could be as simple as a bool[] checked.

In your getView, make sure that you set the checkbox state to the contents of checked[position]. You should also set an OnCheckedChangedListener on your check boxes in getView so that they update your data with checked[position] = isChecked.

Yes, the rows in a ListView are recycled, so make sure to populate all the appropriate data for a row before you leave getView.

Upvotes: 5

Related Questions