onCheckedChanged fired multiple times, Listview with checkbox
Asked Answered
C

3

10

I have a ListView with checkbox:

  1. Oncheckedchanged(..) is called when user check/uncheck item on listview
  2. OncheckedChanged(..) called again when user click the listitem via onItemClick(.....)

Is this a known issue? how to differentiate the events.

public View getView(int position, View convertView, ViewGroup parent) {

ViewHolder viewHolder = null;
if (convertView == null) {
    LayoutInflater inflator = context.getLayoutInflater();
    convertView = inflator.inflate(R.layout.row, null);
    viewHolder = new ViewHolder();
    viewHolder.text = (TextView) convertView.findViewById(R.id.label);
    viewHolder.checkbox = (CheckBox) convertView.findViewById(R.id.check);
    viewHolder.imageview= (ImageView) convertView.findViewById(R.id.imageView1);
    viewHolder.checkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {

                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    int getPosition = (Integer) buttonView.getTag();  // Here we get the position that we have set for the checkbox using setTag.
                    list.get(getPosition).setSelected(buttonView.isChecked()); // Set the value of checkbox to maintain its state.
                }
            });
    convertView.setTag(viewHolder);
    convertView.setTag(R.id.label, viewHolder.text);
    convertView.setTag(R.id.check, viewHolder.checkbox);
    convertView.setTag(R.id.imageView1, viewHolder.imageview);

} else {
    viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.checkbox.setTag(position); // This line is important.
viewHolder.imageview.setTag(position);
viewHolder.text.setText(list.get(position).getName());
viewHolder.checkbox.setChecked(list.get(position).isSelected());


//        change the default-image here
if(list.get(position).getcontact_id()==5)
{
    viewHolder.imageview.setImageResource(android.R.drawable.ic_dialog_map);
}...
..


 return convertView;
 }

EDIT

onCheckedChanged() is called

  1. Once when no item are selected and user clicks the checkbox
  2. If the list consists of 3 items and when user click on any other items, onItemclick() is invoked and onCheckedChanged() is fired 3 times ( =no: of items in the listview)
Cyanamide answered 4/10, 2013 at 18:48 Comment(7)
It'd be great if we could see your code...Natatory
which part of the code-. onclickitem() or customadapter?Cyanamide
I think the place where you're setting your OnCheckChangedListener would be nice to see...Dunseath
@darwind: added code snippetsCyanamide
Can you write the value of isChecked parameter ofonCheckedChanged method to logcat? it should stay true in the extra call.Malaspina
@jboi, and Darwind updated my question please check the EDIT section.Cyanamide
@HpTerm Still same behaviour after applying your suggestion.Cyanamide
M
6

That's expected behavior:

  • onCheckedChanged(CompoundButton buttonView, boolean isChecked) is called for every item, whenever they're checked/unchecked. Android has decided to track all items status for you and calls you for each item every time it was changed. With the isChecked parameter you're able to differentiate what happened.

  • onItemClick() is called whenever one of the items where clicked - that is not necessarily the checkbox within the item, but somewhere. Usually the item is selected afterwards - again, not always.

  • If you need to know which item was actually selected from the list view, use OnItemSelectedListener.onItemSelected(). This is the one called to get the selection (whole item).

BTW: You dont need to prgram the behavior of a checkbox manually. The check/uncheck and drawing of the tick in the box is done by Android. You just need to get the checked status once you know which one was selected. So the onCheckedChanged implementation is not necessary at all as far as I can see.

Malaspina answered 7/10, 2013 at 11:37 Comment(2)
+1 Good answer since it is right... BUT Android has decided WRONG! Its stupid and inconsistent... Other components compensate for value changes via code (progress bar, or at least taken into the listener), other components such as the Spinner, onItemSelected callback also compensate for selecting the selected node.Rouault
Feels a little like "It's not a bug, it's a feature"!Overlook
T
21

Replace the onCheckChangeListener to onClickListener.

The checkChanged will be called twice as it will be called when you call setChecked() method and when you click on the checkbox.

Trocar answered 7/10, 2013 at 8:28 Comment(2)
This is the better advice!!Rouault
but if u change check status without click, like with simple small drag, this wont be called. you may check yourself.Knitting
S
10

I have fixed this issue just by checking:

    mSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
        if(buttonView.isPressed()){
            // do you operation
        });
        }
    });

It avoids multiple calling

Samellasameness answered 15/2, 2019 at 7:54 Comment(0)
M
6

That's expected behavior:

  • onCheckedChanged(CompoundButton buttonView, boolean isChecked) is called for every item, whenever they're checked/unchecked. Android has decided to track all items status for you and calls you for each item every time it was changed. With the isChecked parameter you're able to differentiate what happened.

  • onItemClick() is called whenever one of the items where clicked - that is not necessarily the checkbox within the item, but somewhere. Usually the item is selected afterwards - again, not always.

  • If you need to know which item was actually selected from the list view, use OnItemSelectedListener.onItemSelected(). This is the one called to get the selection (whole item).

BTW: You dont need to prgram the behavior of a checkbox manually. The check/uncheck and drawing of the tick in the box is done by Android. You just need to get the checked status once you know which one was selected. So the onCheckedChanged implementation is not necessary at all as far as I can see.

Malaspina answered 7/10, 2013 at 11:37 Comment(2)
+1 Good answer since it is right... BUT Android has decided WRONG! Its stupid and inconsistent... Other components compensate for value changes via code (progress bar, or at least taken into the listener), other components such as the Spinner, onItemSelected callback also compensate for selecting the selected node.Rouault
Feels a little like "It's not a bug, it's a feature"!Overlook

© 2022 - 2024 — McMap. All rights reserved.