Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CheckBox changes value twice

I have an Android ListView whose items have a checkbox.

The checkbox is checked by default. Once unchecked it should be removed from the list.

The problem is that onCheckedChanged is being fired twice: when I tap the checkbox to uncheck it (with isChecked false) and after I remove the item (with isChecked true).

This is the relevant code of my ArrayAdapter:

public View getView(final int position, View convertView, ViewGroup parent) {
    ViewHolder holder;
    if (convertView == null) {
        convertView = mInflater.inflate(R.layout.item, parent, false);
        holder = new ViewHolder();
        holder.check = (CheckBox) convertView.findViewById(R.id.check);
        convertView.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    }
    final Object item = this.getItem(position);
    holder.check.setOnCheckedChangeListener(new CheckBox.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            if (!isChecked) {
                remove(item); // This somehow calls onCheckedChanged again
            }
        }
    });
    return convertView;
}

What am I doing wrong?

like image 803
hpique Avatar asked Oct 12 '10 10:10

hpique


2 Answers

I encountered the same problem, it seems to be an Android bug this twice execution of onCheckChanged method.

My solution: implement onClickListener, instead of onCheckedChangedListener.

Something like this:

private final class CheckUpdateListener implements OnClickListener {

    private Group parent;
    private boolean isChecked;

    private CheckUpdateListener(Group parent) {

        this.parent = parent;

    }

    @Override
    public void onClick(View box) {
        this.isChecked = !parent.isChecked();

        parent.setChecked(isChecked);

        notifyDataSetChanged();

    }

}
like image 58
Andrei Catinean Avatar answered Nov 07 '22 00:11

Andrei Catinean


I had a similar issue and just resolved it properly without having to avoid using the intended OnCheckedChangeListener.

Problem Code

holder.someCheckBox.setChecked(false);
holder.someCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
    @Override
    public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
       ...
    }
});

Note I set the check status before I set the listener, this was to prevent the listener from firing on creation.

But, the listener started firing the on-check event exactly twice only after the adapter was forced to be re-created or through use of notifyDataSetChanged.

Solution

Clear the listener before setting the check state, even during creation here.

holder.someCheckBox.setOnCheckedChangeListener(null);
holder.someCheckBox.setChecked(false);
holder.someCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
    @Override
    public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
       ...
    }
});

Now any residual listeners will not be fired when setting the initial value of the checkbox.

like image 36
Cord Rehn Avatar answered Nov 07 '22 02:11

Cord Rehn