how to add a listener for checkboxes in an adapter view, Android, ArrayAdapter, onCheckedChanged, OnCheckedChangeListener
Asked Answered
P

4

10

enter image description here

I have a listView that by way of an ArrayAdapter is populated by small xml sub views. each small view only has two things inside, a checkbox and a string label next to it.

i want to set an onCheckedChanged listener to capture the event of the user checking or unchecking the checkboxes.

for example the listener shown here:

 listView.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {

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

 Toast.makeText(this, "box has been checked", Toast.LENGTH_SHORT).show();

 }

}

where do I put the listener code? and how do I set it up?

code for the ArrayAdapter:

  public class MobileArrayAdapter extends ArrayAdapter<CheckBoxInfo>{
    CheckBoxInfo[] objects;
    Context context;
    int textViewResourceId;

    public MobileArrayAdapter(Context context, int textViewResourceId,
        CheckBoxInfo[] objects) {
        super(context, textViewResourceId, objects);
        this.context = context;
        this.textViewResourceId = textViewResourceId;
        this.objects = objects;

    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View row_layout_view = convertView;


            if ((row_layout_view == null)){


                LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                row_layout_view = inflater.inflate(R.layout.row_layout, null);
            }   

          //CheckBoxInfo item = objects.get(position);  // for arrayList
            CheckBoxInfo item = objects[position];

            if(item != null){

            TextView textView = (TextView) row_layout_view.findViewById(R.id.textView1);
            CheckBox checkBox = (CheckBox) row_layout_view.findViewById(R.id.checkBox1);

            if(item !=null){
            textView.setText(item.checkBoxName);
            checkBox.setChecked(item.checkBoxState);
               }
            }
            return row_layout_view;
    }


}
Pushy answered 11/4, 2013 at 5:56 Comment(0)
E
37

Do not use your example listView.setOnCheckedChangeListener or onCheckedChanged code.

First of all, for CheckBox, you should use setOnClickListener() instead of setOnCheckedChangeListener(). You can get the checked state inside of the onClick() function.

Second, place your setOnClickListener() inside of the getView() function of the list adapter.

Example:

checkBox.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View arg0) {
        final boolean isChecked = checkBox.isChecked();
        // Do something here.
    }
});
Easterling answered 11/4, 2013 at 6:1 Comment(2)
I don't think this works because of listview recycling views. As you scroll down and a selected convertView is recycled, the checked row becomes unchecked. How do you get around this?Eelgrass
This is correct behavior. When a View gets reused, all of its sub-view children have the characteristics of the meaningless view that got recycled. Therefore, you must update all views and their attributes in getView() every time. This includes setting the CheckBox value as well as its OnClickListener. In summary, keep the listener and add checkBox.setChecked() to set it to expected value in case recycled (or new) view has a different setting.Easterling
C
1

Thank you David! regarding HukeLau_DABA comment, I solved it by updating the list view object with the CheckBox value inside OnClickListener() . In my case I have a list of places, as can be seen in the next code:

holder.placeCheckBox.setOnClickListener(new View.OnClickListener() {

       //please note that objPlace, position and holder must be declared 
       //as final inside the getView() function scope.   
          @Override
          public void onClick(View arg0) {
                final boolean isChecked = holder.placeCheckBox.isChecked();
                if (isChecked){
                   objPlace.setItemChecked("yes");
                }else{
                   objPlace.setItemChecked("no");
                }

                placesList.set(position,objPlace); //  updating the list with the updated object

            }
      });
Character answered 23/3, 2015 at 14:7 Comment(0)
M
1

do not refer to "holder.placeCheckBox" in your onClickListener, you should refer to view which is passed by onClick and cast it to CheckBox so code should look like this:

holder.placeCheckBox.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View arg0) {
            boolean isChecked = ((CheckBox)arg0).isChecked();
            if (isChecked){
               objPlace.setItemChecked("yes");
            }else{
               objPlace.setItemChecked("no");
            }

            placesList.set(position,objPlace); //  updating the list with the updated object

        }
  });
Michel answered 23/11, 2015 at 7:42 Comment(0)
G
0

You could try this:

holder.placeCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
    @Override
    public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
        Log.d(TAG, "onCheckedChanged: " + holder.placeCheckBox.getText() + " " + (b ? "selected":"deselected"));
    }
});
Gassy answered 23/4, 2016 at 15:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.