0

I implemented a small app two check out some ExpandableListView bugs I have in a bigger app. I read and worked through this and that post. But then I decided to implement the ExpandableListView adapter without the ViewHolder pattern in the first run.

But I still have a bug when opening and closing the parent views. Here is my MainActivity:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ExpandableListView expandableListView = (ExpandableListView) findViewById(R.id.exp_list_view);

        List<Parent> parentList = new ArrayList<>();
        Parent parent;

        List<Child> childList;

        childList = new ArrayList<>();
        childList.add(new Child("One")); childList.add(new Child("Two")); childList.add(new Child("Three"));

        parent = new Parent("First", childList);
        parentList.add(parent);

        childList = new ArrayList<>();
        childList.add(new Child("One")); childList.add(new Child("Two")); childList.add(new Child("Three"));

        parent = new Parent("Second", childList);
        parentList.add(parent);

        childList = new ArrayList<>();
        childList.add(new Child("One")); childList.add(new Child("Two")); childList.add(new Child("Three"));

        parent = new Parent("Third", childList);
        parentList.add(parent);

        childList = new ArrayList<>();
        childList.add(new Child("One")); childList.add(new Child("Two")); childList.add(new Child("Three"));

        parent = new Parent("Forth", childList);
        parentList.add(parent);

        final MyAdapter adapter = new MyAdapter(this, parentList);
        expandableListView.setAdapter(adapter);
    }
}

My adapter class:

class MyAdapter extends BaseExpandableListAdapter {


    private final List<Parent> mParentList;
    private final Context mContext;

    public MyAdapter(final Context context, final List<Parent> parentList) {
        mContext = context;
        mParentList = parentList;
    }

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

    @Override
    public int getChildrenCount(final int groupPosition) {
        return mParentList.get(groupPosition).getChildList().size();
    }

    @Override
    public Object getGroup(final int groupPosition) {
        return mParentList.get(groupPosition);
    }

    @Override
    public Object getChild(final int groupPosition, final int childPosition) {
        return mParentList.get(groupPosition).getChildList().get(childPosition);
    }

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

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

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

    @Override
    public View getGroupView(final int groupPosition, final boolean isExpanded, final View convertView, final ViewGroup parent) {
        View v = convertView;
        if (v == null) {
            LayoutInflater inflater = LayoutInflater.from(mContext);
            v = inflater.inflate(R.layout.row_parent, parent, false);
        }
        TextView tvn = (TextView) v.findViewById(R.id.tv_parent_name);
        tvn.setText(mParentList.get(groupPosition).getName());
        return v;
    }

    @Override
    public View getChildView(final int groupPosition, final int childPosition, final boolean isLastChild, final View convertView, final ViewGroup parent) {
        View row = convertView;
        if (row == null) {
            LayoutInflater inflater = LayoutInflater.from(mContext);
            row = inflater.inflate(R.layout.row_child, parent, false);
        }
        TextView tvn = (TextView) row.findViewById(R.id.tv_child_name);
        Switch sw = (Switch) row.findViewById(R.id.sw_child);
        tvn.setText(mParentList.get(groupPosition).getChildList().get(childPosition).getName());
        sw.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(final CompoundButton buttonView, final boolean isChecked) {
                Log.v(getClass().getName(), "onCheckedChanged() (" + groupPosition + ", " + childPosition + ")");
            }
        });
        return row;
    }

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

And my two model classes. Parent:

public class Parent {
    private String name;
    private List<Child> childList = new ArrayList<>();

    public Parent(final String name, List<Child> childList) {
        this.name = name;
        this.childList = childList;
    }

    public String getName() {
        return name;
    }

    public void setName(final String name) {
        this.name = name;
    }

    public List<Child> getChildList() {
        return childList;
    }

    public void setChildList(final List<Child> childList) {
        this.childList = childList;
    }
}

Child:

public class Child {
    private String name;

    public Child(final String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(final String name) {
        this.name = name;
    }
}

Now I observe the following problem on running the activity. Please follow:

  1. expand all parents (from FIRST to FORTH)
  2. click switches ONE and TWO from parent SECOND and FORTH (from top to bottom)
  3. unexpand all parents (from FIRST to FORTH)
  4. unexpand all parents (from FIRST to FORTH)

observe:

  • second parent: only ONE and TWO are selected
  • third parent: ONE, TWO and THREE are selected
  • forth parent: only TWO is selected

What is going wrong here? Also implementing the ViewHolder pattern didn't work here.

unlimited101
  • 3,653
  • 4
  • 22
  • 41

1 Answers1

0

I had to two things:

  1. Extend the child with the state and track it
  2. Get rid of the if-Statements within getChildView() and getGroupView

My new child class now is:

public class Child {
    private String name;
    private boolean state;

    public Child(final String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(final String name) {
        this.name = name;
    }

    public boolean isState() {
        return state;
    }

    public void setState(final boolean state) {
        this.state = state;
    }
}

My new getChildView() method:

@Override
public View getChildView(final int groupPosition, final int childPosition, final boolean isLastChild, final View convertView, final ViewGroup parent) {
    View view = layoutInflater.inflate(R.layout.child_row, parent, false);

    final Switch sw = (Switch) view.findViewById(R.id.sw);
    TextView textViewChildName = (TextView) view.findViewById(R.id.childname);


    String name = ((Child) getChild(groupPosition, childPosition)).getName();

    sw.setChecked(list.get(groupPosition).getChildList().get(childPosition).isState());

    textViewChildName.setText(name);

    sw.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(final CompoundButton buttonView, final boolean isChecked) {
            list.get(groupPosition).getChildList().get(childPosition).setState(isChecked);
            sw.setChecked(isChecked);
        }
    });

    return view;
}

And finally getGroupView():

@Override
public View getGroupView(final int groupPosition, final boolean isExpanded, final View convertView, final ViewGroup parent) {
    View view = layoutInflater.inflate(R.layout.group_row, parent, false);
    TextView textView = (TextView) view.findViewById(R.id.groupname);

    String name = ((Parent) getGroup(groupPosition)).getName();
    textView.setText(name);

    return view;
}

I had to quit with the ViewHolder pattern. It doesn't work for my because I am using the switch and wanna keep the state.

unlimited101
  • 3,653
  • 4
  • 22
  • 41