Q:

Expand/collapse a nested RecyclerView

I have a RecyclerView adapter with multiple ViewHolders. Each ViewHolder has a header TextView and a nested RecyclerView which was working fine. But I wanted to implement an expand/collapse function so that nested RecyclerView is hidden until the header is clicked. I used this method RecyclerView expand/collapse items. It works but when I click the header to expand the nested recylerview, the recyclerview doesn't populate any data. To be clear, it retrieves data but it's not visible. Any ideas why this might be? 
This is my onBindViewMethod:
public class EligibilityAdapter extends RecyclerView.Adapter<EligibilityAdapter.ViewHolder> {

private Context mContext;
private List<EligibilityDetails> mEligsList;
private List<Items> mItemslist;
private LayoutInflater inflater;
private int mExpandedPosition = -1;

public EligibilityAdapter(Context context, List<EligibilityDetails> eligsList) {
    mContext = context;
    mEligsList = eligsList;
    inflater = LayoutInflater.from(context);
}

@Override
public int getItemViewType(int position) {
    switch (position) {
        case 0:
            return R.layout.rv_eligs_item_domestic;
        case 1:
            return R.layout.rv_eligs_item_overseas;
        default:
            return R.layout.rv_eligs_item_military;
    }
}

@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
    inflater = LayoutInflater.from(viewGroup.getContext());
    View view = inflater.inflate(i, viewGroup, false);
    ViewHolder holder = null;
    switch (i) {
        case R.layout.rv_eligs_item_domestic:
            holder = new DomesticViewHolder(view);
            break;
        case R.layout.rv_eligs_item_overseas:
            holder = new OverseasViewHolder(view);
            break;
        case R.layout.rv_eligs_item_military:
            holder = new MilitaryViewHolder(view);
            break;
    }
    return holder;
}

@Override
public int getItemCount() {
    return mEligsList.size();
}

public abstract class ViewHolder extends RecyclerView.ViewHolder {
    RecyclerView itemsRv;
    TextView mHeader;
    ItemsAdapter adapter;

    public ViewHolder(View itemView) {
        super(itemView);
        mHeader = (TextView) itemView.findViewById(R.id.header_tv);
        itemsRv = itemView.findViewById(R.id.recyclerViewItems);
    }
    public void setData(List<Items> list) {
        adapter.updateList(list);
    }
    abstract void bind(EligibilityDetails item);
}

public class DomesticViewHolder extends ViewHolder {

    TextView mHeader;
    RecyclerView itemsRv;
    ItemsAdapter adapter;

    public DomesticViewHolder(View itemView) {
        super(itemView);
        mHeader = (TextView) itemView.findViewById(R.id.header_tv);
        itemsRv = itemView.findViewById(R.id.recyclerViewItems);
    }
    public void setData(List<Items> list) {
        adapter.updateList(list);
    }
    @Override
    void bind(EligibilityDetails eligibilityDetails) {
        mHeader.setText(eligibilityDetails.getRequirementHeader());
        mItemslist = eligibilityDetails.getItemsList();
        ItemsAdapter itemsAdapter = new ItemsAdapter(mContext, mItemslist);
        itemsRv.setHasFixedSize(true);
        itemsRv.setLayoutManager(new CustomLinearLayoutManager(mContext));
        itemsRv.setAdapter(itemsAdapter);
        itemsRv.setNestedScrollingEnabled(false);
    }
}

public class OverseasViewHolder extends ViewHolder {

    TextView mHeader;
    RecyclerView itemsRv;
    ItemsAdapter adapter;

    public OverseasViewHolder(View itemView) {
        super(itemView);
        mHeader = (TextView) itemView.findViewById(R.id.header_tv);
        itemsRv = itemView.findViewById(R.id.recyclerViewItems);
    }
    public void setData(List<Items> list) {
        adapter.updateList(list);
    }

    @Override
    void bind(EligibilityDetails eligibilityDetails) {
        mHeader.setText(eligibilityDetails.getRequirementHeader());
        mItemslist = eligibilityDetails.getItemsList();
        ItemsAdapter itemsAdapter = new ItemsAdapter(mContext, mItemslist);
        itemsRv.setHasFixedSize(true);
        itemsRv.setLayoutManager(new CustomLinearLayoutManager(mContext));
        itemsRv.setAdapter(itemsAdapter);
        itemsRv.setNestedScrollingEnabled(false);
    }
}

public class MilitaryViewHolder extends ViewHolder {

    TextView mHeader;
    RecyclerView itemsRv;
    ItemsAdapter adapter;

    public MilitaryViewHolder(View itemView) {
        super(itemView);
        mHeader = (TextView) itemView.findViewById(R.id.header_tv);
        itemsRv = itemView.findViewById(R.id.recyclerViewItems);
    }
    public void setData(List<Items> list) {
        adapter.updateList(list);
    }

    @Override
    void bind(EligibilityDetails eligibilityDetails) {
        mHeader.setText(eligibilityDetails.getRequirementHeader());
        mItemslist = eligibilityDetails.getItemsList();
        final ItemsAdapter itemsAdapter = new ItemsAdapter(mContext, mItemslist);
        itemsRv.setHasFixedSize(true);
        itemsRv.setLayoutManager(new CustomLinearLayoutManager(mContext));
        itemsRv.setAdapter(itemsAdapter);
        itemsRv.setNestedScrollingEnabled(false);
    }
}

@Override
public void onBindViewHolder(@NonNull final EligibilityAdapter.ViewHolder viewHolder, int i) {
    viewHolder.bind(mEligsList.get(i));

    final boolean isExpanded = i == mExpandedPosition;
    viewHolder.itemsRv.setVisibility(isExpanded?View.VISIBLE:View.GONE);
    viewHolder.itemView.setActivated(isExpanded);
    viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            mExpandedPosition = isExpanded ? -1:viewHolder.getAdapterPosition();
            ItemsAdapter itemsAdapter = new ItemsAdapter(mContext, mItemslist);
            viewHolder.itemsRv.setAdapter(itemsAdapter);
            //TransitionManager.beginDelayedTransition(recyclerView);
            notifyDataSetChanged();
        }
    });
}

where itemsRv is the nested RecyclerView.
I've tried moving this logic to the individual viewholders and moving the recyclerview logic here like setting the adapter inside of the onClick method. Each time it comes up blank.
Thanks in advance.

A:

Instead of having a new sub Recyclerview for every header you can create a multi view-type adapter that will have a view-type for your header and a view-type for your child-item.
And instead of using a just the header data-item for your list of data, use a generic type that will allow casting each data-type to its own view-type.
To do that we need to create an empty interface that all of our data-types will implement that way they are all generic.
public interface GenericDataType {}

so then your data-type will look like this
class HeaderItem implements GenericDataType {
    //All of your pojo data
    List<ChildrenItem> childrens; //ChildrenItem will also implement the GenericDataType that way both of the items are acceptable
}

So ones we did that we can replace the current items from
private List<EligibilityDetails> mEligsList;
private List<Items> mItemslist;

To
private List<GenericDataType> adapterItems;

Now we need to make sure that whenever we have a certain ViewHolder the item of that position will be of the right type. In order to do that we need to change our getItemViewType
@Override
public int getItemViewType(int position) {
    GenericItem currentItem = adapterItems.get(position);

    if (currentItem instanceOf HeaderItem) { //We have to use if else becasue java's switch does not supprt checking instancesOf
        return R.layout.your_header_item_layout_id;

    } else if(currentItem instanceOf ChildrenItem) {
        return R.layout.your_children_item_layout_id;

    } else if(repeat for any other types you have) {
        return R.layout.your_other_item_layout_id;

    } else {
        throw new Throwable("Unsupported type"); //This should never happen but we add it to make the compiler compile
    }
}

Now we can finally change our onBind method to support both types
@Override
public void onBindViewHolder(@NonNull final  EligibilityAdapter.ViewHolder viewHolder, int i) {

    if (viewHolder instanceOf HeaderViewHolder) {
        HeaderViewHolder holder = (HeaderViewHolder) viewHolder;
        headerItem = (HeaderItem) items.get(i);
        //Do rest of binding here

        holder.viewToAddMoreItems.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (!headerItem.isEpanded()) { //Add to your header type a Boolean to check if it is expanded or not 
                    adapterItems.addAll(headerItem.getChildrens()); //They are the same generic type but the getItemViewType will handle it for us
                    notifyItemRangeInserted(); //Provied item start index and size of the list
                } else {
                    adapterItems.removeAll(headerItem.getChildrens());
                    notifyItemRangeRemoved(); I don't remember what it require but you'll figure that out
                }
                headerItem.setExpanded(!headerItem.isExpanded()); //Flipping the value 
            }
        });

    } else if (viewHolder instanceOf ChildrenViewHolder) {
            ChildrenViewHolder holder = (ChildrenViewHolder) viewHolder;
            childrenItem = (ChildrenItem) items.get(i);
            //Do your binding here

    } else if(repeate for other view-types) {}
}

