Nested RecyclerViews

In this guide, we'll be looking at how to implement a nested RecyclerView. We'll be having two RecyclerViews, one of it being a parent of a child RecylerView.

Although it is NOT encouraged to do this in practice, but it is good to know such complex layout can be done with it.

Source, please see at the bottom.

p/s: I haven't tried having many items loaded with this approach.

Layout structuring

Initial planning:

recyclerviewception-initial-planning

RecyclerView Parent (R.id.rv_parent)  
    - Items as CardView
        - RecyclerView Child (R.id.rv_child)
            - Items as Linear:Vertical listing with Custom LinearLayoutManager

Additional library

android-linear-layout-manager

Because existing LinearLayoutManager in Support Library API doesn't support height WRAP_CONTENT, this library will help us doing that.

Implementation

In ParentFragment, we're using standard LinearLayoutManager in Support Library. Pass both Parent and Child data to the Adapter.

LinearLayoutManager manager = new LinearLayoutManager(getActivity());  
manager.setOrientation(LinearLayoutManager.VERTICAL);  
recyclerViewParent.setLayoutManager(manager);  
recyclerViewParent.setHasFixedSize(true);

ParentAdapter parentAdapter = new ParentAdapter(getActivity(), getParentChildData());  
recyclerViewParent.setAdapter(parentAdapter);  

In ParentAdapter, only thing we need to do is to have another RecyclerView as the item view of our Parent.

private void initChildLayoutManager(RecyclerView rv_child, ArrayList<Child> childData) {  
    org.solovyev.android.views.llm.LinearLayoutManager manager = new org.solovyev.android.views.llm.LinearLayoutManager(ctx, LinearLayoutManager.VERTICAL, false);
    rv_child.setLayoutManager(manager);
    rv_child.setHasFixedSize(true);

    // disable touch gesture on our Child RV
    rv_child.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
        @Override
        public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) { return true; }
        @Override
        public void onTouchEvent(RecyclerView rv, MotionEvent e) {}
        @Override
        public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {}
    });

    ChildAdapter childAdapter = new ChildAdapter(childData); // pass child data to Child Adapter
    rv_child.setAdapter(childAdapter);
}

By using a custom LinearLayoutManager, our Child view items won't get squeezed by the Parent's view item.

This is a known bug/issue in RecyclerView API and is now being made into next API release.

UPDATE: Support Library 23.2 release fixes this issue.

Source code


Reference

Aiman Baharum

More about this blog https://github.com/aimanbaharum/random-wiki/wiki

Kuala Lumpur, Malaysia http://www.aimanbaharum.com

Subscribe to Knowledge Log

Get the latest posts delivered right to your inbox.

or subscribe via RSS with Feedly!