3

I feel rather stupid for not noticing this before but when I scroll up and down in my app, the checkboxes randomly check and uncheck. The checkboxes are on the GroupView and not the Child element of the Expandable ListView. I have done a lot of research into this and realise that the problem is recycling views and something to do with the onCheckedChangeListener. I also know (sort of) what I have to do to solve the problem. Thing is, I am not sure how to implement it. This is because all research leads to fixes for people using checkboxes ListView or fixes for checkboxes in the ChildView of an Expandable ListView

Here is the tutorial I used for Expandable ListView

Below are other links I have found relating to my issue, sort. None of them can particularly help:

Android ListView with Checkbox: automatically unchecks

Android, Checkboxes Randomly Checked/Unchecked in Expandable List

checkbox unchecked when i scroll listview in android

ListView with CheckBox Scrolling Issue

Expandable listview with selectall checkbox : group itemclick and scrolling bug

Below is some code that I hope will shed some light on things:

ExpandableListAdapter.java: Now updated based on first answer

public class ExpandableListAdapter extends BaseExpandableListAdapter {

private Context _context;
private List<String> _listDataHeader; // header titles
// child data in format of header title, child title
private HashMap<String, List<String>> _listDataChild;

boolean checkAll_flag = false;
boolean checkItem_flag = false;

public ExpandableListAdapter(Context context, List<String> listDataHeader,
        HashMap<String, List<String>> listChildData) {
    this._context = context;
    this._listDataHeader = listDataHeader;
    this._listDataChild = listChildData;
}

@Override
public Object getChild(int groupPosition, int childPosititon) {
    return this._listDataChild.get(this._listDataHeader.get(groupPosition))
            .get(childPosititon);
}

@Override
public long getChildId(int groupPosition, int childPosition) {
    return childPosition;
}

@Override
public View getChildView(int groupPosition, final int childPosition,
        boolean isLastChild, View convertView, ViewGroup parent) {

    final String childText = (String) getChild(groupPosition, childPosition);

    if (convertView == null) {
        LayoutInflater infalInflater = (LayoutInflater) this._context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = infalInflater.inflate(R.layout.suikoden_list_item1, null);
    }

    TextView txtListChild = (TextView) convertView
            .findViewById(R.id.lblListItem);

    txtListChild.setText(childText);
    return convertView;
}

@Override
public int getChildrenCount(int groupPosition) {
    return this._listDataChild.get(this._listDataHeader.get(groupPosition))
            .size();
}

@Override
public Object getGroup(int groupPosition) {
    return this._listDataHeader.get(groupPosition);
}

@Override
public int getGroupCount() {
    return this._listDataHeader.size();
}

@Override
public long getGroupId(int groupPosition) {
    return groupPosition;
}

class ExpanableValue
{
  String title;
  boolean isChecked;


  // setter and getter

}

@Override
public View getGroupView(int groupPosition, boolean isExpanded,
        View convertView, ViewGroup parent) {


    if (convertView == null) {
        LayoutInflater infalInflater = (LayoutInflater) this._context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = infalInflater.inflate(R.layout.suikoden_list_group1, null);
        //convertView.setTag(gholder);

    //}else{
        //gholder = (GroupViewHolder)convertView.getTag();
    }

    /////////////////////

    CheckBox cb = (CheckBox)convertView
            .findViewById(R.id.checkboxTick);
    cb.setTag(groupPosition);
    cb.setOnClickListener(this);
    cb.setCheck(groupList.get(groupPosition).isChecked());
    ////////////////////

    TextView lblListHeader = (TextView) convertView
            .findViewById(R.id.lblListHeader);
    lblListHeader.setTypeface(null, Typeface.BOLD);
    lblListHeader.setText(groupList.get(groupPosition).getTitle());

    return convertView;
}

public void onClick(View v) {

     switch(v.getId())
    {
      case R.id.checkboxTick:
        int pos = (Integer) arg0.findViewById(R.id.checkboxTick).getTag();
            groupList.get(pos).setChecked((CheckBox)v.isChecked());
            break;
    }
}

@Override
public boolean hasStableIds() {
    return false;
}

@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
    return true;
}

}

CheckBox in SuikodenFragment.java:

@Override
public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) {
    CheckBox checkBox = (CheckBox) expListView.findViewById(R.id.checkboxTick);
    checkBox.setOnCheckedChangeListener(null);
    if (isChecked)
        // Add the tick to the box
        //Log.d(TAG, "Tick the box");
        checked = true;
     else
        // Remove the tick in the box
        //Log.d(TAG, "Untick the box");
         checked = false;
}

If anyone could suggest a fix, or provide sample code or any other help that would be great! Thanks in advance!

Community
  • 1
  • 1
theCreed
  • 55
  • 11
  • you need save state of check box then read that in getChild view method, if you don't get me, post code of `ExpandableListAdapter` – Shayan Pourvatan Jun 15 '14 at 11:17
  • @shayanpourvatan Thanks for the reply, I have update the code to include all of the ExpandableListAdapter code. But the checkbox is not in the ChildView (the drop down) its in the GroupView. For example, my list is CheckBox - Character Name > then dropdown to character info. So the CheckBox is in the GroupView. Thanks! – theCreed Jun 15 '14 at 11:32
  • where you initialize that in `GroupView`? i don't see that – Shayan Pourvatan Jun 15 '14 at 11:34
  • @shayanpourvatan my Checkbox is implemented in a different fragment, the code for that is in my first post. Although I have seen in some solutions that the onCheckedChanged method should be placed inside the ExpandableListView – theCreed Jun 15 '14 at 11:39

1 Answers1

1

create one class like:

class ExpanableValue
{
  String title;
  boolean isChecked;


  // setter and getter

}

instead of List<String> pass one List of ExpanableValue (or what ever you want call that).

then in getGroupView:

@Override
public View getGroupView(int groupPosition, boolean isExpanded,
        View convertView, ViewGroup parent) {


    if (convertView == null) {
        LayoutInflater infalInflater = (LayoutInflater) this._context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = infalInflater.inflate(R.layout.suikoden_list_group1, null);
        //convertView.setTag(gholder);

    //}else{
        //gholder = (GroupViewHolder)convertView.getTag();
    }

    /////////////////////

    CheckBox cb = (CheckBox)convertView
            .findViewById(R.id.checkBoxID);
    cb.setTag(groupPosition);
    cb.setOnClickListener(this);
    cb.setCheck(groupList.get(groupPosition).isChecked());
    ////////////////////

    TextView lblListHeader = (TextView) convertView
            .findViewById(R.id.lblListHeader);
    lblListHeader.setTypeface(null, Typeface.BOLD);
    lblListHeader.setText(groupList.get(groupPosition).getTitle());

    return convertView;
}

then in onClick method:

@Override
public void onClick(View v) {

     switch(v.getId())
    {
      case R.id.checkBoxID:
        int pos = (Integer) v.findViewById(R.id.checkBoxID).getTag();
            groupList.get(pos).setChecked((CheckBox)v.isChecked());
            break;
    }
}

it is better to use ViewHolder in getGroupView,

Shayan Pourvatan
  • 11,898
  • 4
  • 42
  • 63
  • Thanks for this i will implement it as soon as possible. Just a quick question, do i place all this new code in the ExpandableListView? – theCreed Jun 15 '14 at 11:51
  • yes, use my `getGroupView` but you need change something more, i said in my post, add onClick if you not and you need implement `onClickListener` to and Create one class as i said – Shayan Pourvatan Jun 15 '14 at 11:53
  • Thank you so much for all your help. I am a beginner so I am sorry that I keep asking questions. I am currently getting a couple of errors. Every time it says 'groupList' I get a cannot resolve error. 'arg0' in the onClick gives the same error. The final two errors are on 'cb.setOnClickListener' and 'v.isChecked()' in onClick. I have updated the code, thanks – theCreed Jun 15 '14 at 13:04
  • change `arg0` to `v`, and you must send `groupList` to constructor, instead of `listDataHeader` – Shayan Pourvatan Jun 15 '14 at 13:10