Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

multiple lists checkboxes getting messed up

Tags:

android

I have 500+ items to put in a checklist divided into categories. My solution so far for this is to use multiple expandableListView lists and the items inside them of course. The problem shows up when I check some of the check boxes, the get messed up and check boxes from another lists get checked and I dont know why.. Can someone throw some light here?

ExpandableListView.java

public class IngredientsExpandableList extends ExpandableListActivity {
// Create ArrayList to hold parent Items and Child Items
private ArrayList<ParentModel> parentItems = new ArrayList<ParentModel>();
private ArrayList<ChildModel> childItems = new ArrayList<ChildModel>();

@Override
public void onCreate(Bundle savedInstanceState)
{

    super.onCreate(savedInstanceState);

    // Create Expandable List and set it's properties
    ExpandableListView expandableList = getExpandableListView();
    expandableList.setDividerHeight(0);
    expandableList.setGroupIndicator(null);
    expandableList.setClickable(true);

    //Setting the data.
    setData();

    // Create the Adapter
    MyExpandableAdapter adapter = new MyExpandableAdapter(parentItems, childItems);

    adapter.setInflater(LayoutInflater.from(this), this);

    // Set the Adapter to expandableList
    expandableList.setAdapter(adapter);
    expandableList.setOnChildClickListener(this);
}
public void setData(){
    String[] colors = getResources().getStringArray(R.array.ingredientsColor);
    String[] innerColors = getResources().getStringArray(R.array.ingredientsInnerColor);

    // Set the Items of Parent
    for (int i = 0; i < 10; i++){
        parentItems.add(new ParentModel("ingredients "+(i+1), Color.parseColor(colors[i])));
    }
    // Set The Child Data
    ArrayList<String> child = null;
    for (int i = 0; i < parentItems.size(); i++){
        child = new ArrayList<String>();
        for (int k = 0; k < 4; k++){
            child.add("ingredient " + (k+1));
        }
        childItems.add(new ChildModel(child,Color.parseColor(innerColors[i])));
    }
}
public void makeToast(String string){
    Toast.makeText(this, string,
            Toast.LENGTH_SHORT).show();
}
public class ParentModel{
    String text;
    int color;
    public ParentModel(String text, int color) {
        this.text = text;
        this.color = color;
    }
    public String getText() {
        return text;
    }

    public int getColor() {
        return color;
    }
}
public class ChildModel{
    ArrayList<String> text;
    int color;
    public ChildModel(ArrayList<String> text, int color) {
        this.text = text;
        this.color = color;
    }
    public ArrayList<String> getText() {
        return text;
    }

    public int getColor() {
        return color;
    }
}
public class MyExpandableAdapter extends BaseExpandableListAdapter
{

    private Activity activity;
    private ArrayList<ChildModel> childItems;
    private LayoutInflater inflater;
    private ArrayList<ParentModel> parentItems;
    private ArrayList<String> child;

    // constructor
    public MyExpandableAdapter(ArrayList<ParentModel> parents, ArrayList<ChildModel> childern)
    {
        this.parentItems = parents;
        this.childItems = childern;
    }

    public void setInflater(LayoutInflater inflater, Activity activity)
    {
        this.inflater = inflater;
        this.activity = activity;
    }

    // method getChildView is called automatically for each child view.
    //  Implement this method as per your requirement
    @Override
    public View getChildView(int groupPosition, final int childPosition, boolean isLastChild, View convertView, ViewGroup parent)
    {

        child = childItems.get(groupPosition).getText();

        TextView textView = null;
        CheckBox checkBox = null;
        LinearLayout LinearView = null;

        if (convertView == null) {
            convertView = inflater.inflate(R.layout.child_list, null);
        }

        // get the textView reference and set the value
        textView = (TextView) convertView.findViewById(R.id.textView1);
        textView.setText(child.get(childPosition));

        LinearView = (LinearLayout) convertView.findViewById(R.id.layout);
        LinearView.setBackgroundColor(childItems.get(groupPosition).getColor());

        checkBox = (CheckBox) convertView.findViewById(R.id.checkBox1);

        // set the ClickListener to handle the click event on child item
        convertView.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View view) {
                makeToast("clicked");
            }
        });
        return convertView;
    }

    // method getGroupView is called automatically for each parent item
    // Implement this method as per your requirement
    @Override
    public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent)
    {

        if (convertView == null) {
            convertView = inflater.inflate(R.layout.parent_list, null);
        }

        ((CheckedTextView) convertView.findViewById(R.id.textViewGroup)).setText(parentItems.get(groupPosition).getText());
        ((CheckedTextView) convertView.findViewById(R.id.textViewGroup)).setBackgroundColor(parentItems.get(groupPosition).getColor());
        ((CheckedTextView) convertView.findViewById(R.id.textViewGroup)).setChecked(isExpanded);


        return convertView;
    }

    @Override
    public Object getChild(int groupPosition, int childPosition)
    {
        return null;
    }

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

    @Override
    public int getChildrenCount(int groupPosition)
    {
        return childItems.get(groupPosition).getText().size();
    }

    @Override
    public Object getGroup(int groupPosition)
    {
        return null;
    }

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

    @Override
    public void onGroupCollapsed(int groupPosition)
    {
        super.onGroupCollapsed(groupPosition);
    }

    @Override
    public void onGroupExpanded(int groupPosition)
    {
        super.onGroupExpanded(groupPosition);
    }

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

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

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

}
}
like image 836
FlyingNades Avatar asked Feb 01 '26 04:02

FlyingNades


1 Answers

This is because views are recycled in lists so you must store the state of the checks and make sure you set them inside the get child view. something like this

public class IngredientsExpandableList extends ExpandableListActivity {
// Create ArrayList to hold parent Items and Child Items
private ArrayList<ParentModel> parentItems = new ArrayList<ParentModel>();
private ArrayList<ChildModel> childItems = new ArrayList<ChildModel>();

@Override
public void onCreate(Bundle savedInstanceState)
{

    super.onCreate(savedInstanceState);

    // Create Expandable List and set it's properties
    ExpandableListView expandableList = getExpandableListView();
    expandableList.setDividerHeight(0);
    expandableList.setGroupIndicator(null);
    expandableList.setClickable(true);

    //Setting the data.
    setData();

    // Create the Adapter
    MyExpandableAdapter adapter = new MyExpandableAdapter(parentItems, childItems);

    adapter.setInflater(LayoutInflater.from(this), this);

    // Set the Adapter to expandableList
    expandableList.setAdapter(adapter);
    expandableList.setOnChildClickListener(this);
}
public void setData(){
    String[] colors = getResources().getStringArray(R.array.ingredientsColor);
    String[] innerColors = getResources().getStringArray(R.array.ingredientsInnerColor);

    // Set the Items of Parent
    for (int i = 0; i < 10; i++){
        parentItems.add(new ParentModel("ingredients "+(i+1), Color.parseColor(colors[i])));
    }
    // Set The Child Data
    ArrayList<String> child = null;
    for (int i = 0; i < parentItems.size(); i++){
        child = new ArrayList<String>();
        for (int k = 0; k < 4; k++){
            child.add("ingredient " + (k+1));
        }
        childItems.add(new ChildModel(child,Color.parseColor(innerColors[i])));
    }
}
public void makeToast(String string){
    Toast.makeText(this, string,
            Toast.LENGTH_SHORT).show();
}
public class ParentModel{
    String text;
    int color;
    public ParentModel(String text, int color) {
        this.text = text;
        this.color = color;
    }
    public String getText() {
        return text;
    }

    public int getColor() {
        return color;
    }
}
public class ChildModel{
    ArrayList<String> text;
    int color;
    ArrayList<Boolean> checked = new ArrayList();;

    public ChildModel(ArrayList<String> text, int color) {
        this.text = text;
        this.color = color;
        for(String i:text)
        {
            checked.add(false);
        }
    }
    public ArrayList<String> getText() {
        return text;
    }

    public int getColor() {
        return color;
    }
}
public class MyExpandableAdapter extends BaseExpandableListAdapter
{

    private Activity activity;
    private ArrayList<ChildModel> childItems;
    private LayoutInflater inflater;
    private ArrayList<ParentModel> parentItems;
    private ArrayList<String> child;

    // constructor
    public MyExpandableAdapter(ArrayList<ParentModel> parents, ArrayList<ChildModel> childern)
    {
        this.parentItems = parents;
        this.childItems = childern;
    }

    public void setInflater(LayoutInflater inflater, Activity activity)
    {
        this.inflater = inflater;
        this.activity = activity;
    }

    // method getChildView is called automatically for each child view.
    //  Implement this method as per your requirement
    @Override
    public View getChildView(int groupPosition, final int childPosition, boolean isLastChild, View convertView, ViewGroup parent)
    {

        child = childItems.get(groupPosition).getText();

        TextView textView = null;
        CheckBox checkBox = null;
        LinearLayout LinearView = null;

        if (convertView == null) {
            convertView = inflater.inflate(R.layout.child_list, null);
        }

        // get the textView reference and set the value
        textView = (TextView) convertView.findViewById(R.id.textView1);
        textView.setText(child.get(childPosition));

        LinearView = (LinearLayout) convertView.findViewById(R.id.layout);
        LinearView.setBackgroundColor(childItems.get(groupPosition).getColor());

        checkBox = (CheckBox) convertView.findViewById(R.id.checkBox1);
        checkBox.setChecked(childItems.get(groupPosition).checked.get(childPosition));


        checkbox.setOnCheckedChangeListener(new OnCheckedChangeListener()
        {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
            {
                childItems.get(groupPosition).checked.get(childPosition) = isChecked;
            }
        });
                    // set the ClickListener to handle the click event on child item
        convertView.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View view) {
                makeToast("clicked");
            }
        });
        return convertView;
    }

    // method getGroupView is called automatically for each parent item
    // Implement this method as per your requirement
    @Override
    public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent)
    {

        if (convertView == null) {
            convertView = inflater.inflate(R.layout.parent_list, null);
        }

        ((CheckedTextView) convertView.findViewById(R.id.textViewGroup)).setText(parentItems.get(groupPosition).getText());
        ((CheckedTextView) convertView.findViewById(R.id.textViewGroup)).setBackgroundColor(parentItems.get(groupPosition).getColor());
        ((CheckedTextView) convertView.findViewById(R.id.textViewGroup)).setChecked(isExpanded);


        return convertView;
    }

    @Override
    public Object getChild(int groupPosition, int childPosition)
    {
        return null;
    }

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

    @Override
    public int getChildrenCount(int groupPosition)
    {
        return childItems.get(groupPosition).getText().size();
    }

    @Override
    public Object getGroup(int groupPosition)
    {
        return null;
    }

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

    @Override
    public void onGroupCollapsed(int groupPosition)
    {
        super.onGroupCollapsed(groupPosition);
    }

    @Override
    public void onGroupExpanded(int groupPosition)
    {
        super.onGroupExpanded(groupPosition);
    }

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

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

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

}
like image 75
Tomer Shemesh Avatar answered Feb 02 '26 19:02

Tomer Shemesh