0

I have an expandlist that has 6 items, when the 3rd can expand to another list of 12.

Everything works great, expands, collapses, opens fragments... my problem is that I can't set the items checked (change its background) only in a very specific case: when I choose a child item (from the 3rd expanded list), not closing the expanded list, and choosing an item below the expand list (bigger than 2).

for example: I choose item 2, the list expanded, then I scroll down and choose the last item from the first (group) list - it works but it is check (changes bg) of the 3rd item instaed of the 6th!

I guess it has something with a recycle view, bu I can't figure it out. I googled a lot but didn't find a working example. Is it possible at all?

Please help. Tnx

mMenuAdapter = new ExpandableListAdapter (this, listDataHeader, listDataChild, expandableList);

expandableList.setAdapter (mMenuAdapter);



expandableList.setOnGroupClickListener (new ExpandableListView.OnGroupClickListener () {
            @Override
            public boolean onGroupClick (ExpandableListView expandableListView, View view, int i, long l) {

                if (currentView != null)
                    currentView.setBackgroundColor (getResources ().getColor (R.color.transparent));


                if (expandableListView.isGroupExpanded (2))
                    expandableListView.collapseGroup (2);


                if (i != 2) {
                    currentView = view;
                    currentView.setBackgroundColor (getResources ().getColor (R.color.veryLightBg));
                } else {
                    currentView = null;
                    return false;
                }

                mainMenuClicked (i); // opens the right fragment

                return true;
            }
        });


expandableList.setOnChildClickListener (new ExpandableListView.OnChildClickListener () {
            @Override
            public boolean onChildClick (ExpandableListView expandableListView, View view, int i, int i1, long l) {

                if (currentView != null)
                    currentView.setBackgroundColor (getResources ().getColor (R.color.transparent));

                currentView = view;
                currentView.setBackgroundColor (getResources ().getColor (R.color.veryLightBg));

                childMenuClicked (i1);
                return false;
            }
        });

The adapter:


public class ExpandableListAdapter extends BaseExpandableListAdapter {

    private Context mContext;
    private List<ExpandedMenuItem> mListDataHeader; 
    private HashMap<ExpandedMenuItem, List<String>> mListDataChild;
    ExpandableListView expandList;


    public ExpandableListAdapter(Context context, List<ExpandedMenuItem> listDataHeader, HashMap<ExpandedMenuItem, List<String>> listChildData, ExpandableListView mView) {
        this.mContext = context;
        this.mListDataHeader = listDataHeader;
        this.mListDataChild = listChildData;
        this.expandList = mView;
    }


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


    public int getChildrenCount(int groupPosition) {
        int childCount = 0;
        if (groupPosition == 2)
            childCount = this.mListDataChild.get(this.mListDataHeader.get(groupPosition)).size();

        return childCount;
    }


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


    @Override
    public Object getChild(int groupPosition, int childPosition) {
        return this.mListDataChild.get(this.mListDataHeader.get(groupPosition)).get(childPosition);
    }


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


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


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


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

        ExpandedMenuItem headerTitle = (ExpandedMenuItem) getGroup(groupPosition);

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

        TextView lblListHeader = convertView.findViewById(R.id.single_menu);

        if (groupPosition == 2) {
            if (!isExpanded)
                lblListHeader.setText (mContext.getString (R.string.products_category));
            else
                lblListHeader.setText (mContext.getString (R.string.expand_products_category));


        } else {
            lblListHeader.setText (headerTitle.getName ());
        }

        return convertView;
    }



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

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

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

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

        txtListChild.setText(childText);

        return convertView;
    }


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

Avital
  • 549
  • 5
  • 15

1 Answers1

0

After many searches I came up with complete answer.

First, I added a checkableRowLayout class (as this answer suggests) for the list view, so it can be checked:

public class checkableRowLayout extends ConstraintLayout implements Checkable {

    private boolean isChecked = false;


    public checkableRowLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public boolean isChecked() {
        return isChecked;
    }

    public void setChecked(boolean isChecked) {
        this.isChecked = isChecked;
        changeColor(isChecked);
    }

    public void toggle() {
        this.isChecked = !this.isChecked;
        changeColor(this.isChecked);
    }

    private void changeColor(boolean isChecked){
        if (isChecked) {
            setBackgroundColor(getResources().getColor(R.color.veryveryLightGrey));
        } else {
            setBackgroundColor(getResources().getColor(android.R.color.transparent));
        }
    }
}

Next, I set this class in the xml source file of the list row (instead of "LinearLayout" as a root view), notice to do it for both views if you have different view for the main list items and the sub items:

<?xml version="1.0" encoding="utf-8"?>
<com.myapp.togo.checkableRowLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="20sp"
        android:textColor="@color/blue"
        android:textSize="20sp"
        android:id="@+id/title"
        android:paddingBottom="15sp"
        android:paddingTop="15sp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"/>

</com.myapp.togo.checkableRowLayout>

I added 2 lines in the click listeners for the group and the child list items:

expandableList.setOnChildClickListener (new ExpandableListView.OnChildClickListener () {
            @Override
            public boolean onChildClick (ExpandableListView expandableListView, View view, int i, int i1, long l) {

                expandableList.setItemChecked(i+i1+1, true); // this is the new line
                expandableList.setSelection(i+i1+1); // this is the new line
                
                childMenuClicked (i1);

                return false;
            }
        });
expandableList.setOnGroupClickListener (new ExpandableListView.OnGroupClickListener () {
            @Override
            public boolean onGroupClick (ExpandableListView expandableListView, View view, int i, long l) {

                if (expandableListView.isGroupExpanded (2))
                    expandableListView.collapseGroup (2);

                expandableList.setItemChecked(i, true); // this is the new line
                expandableList.setSelection(i); // this is the new line
                
                if (i == 2)
                    return false;
                
                mainMenuClicked (i);

                return true;
            }
        });

Now it works. I hopw you find it helpful!

Avital
  • 549
  • 5
  • 15