Android Nested RecyclerViews with expandable list
The following is an example for creating nested RecyclerViews in Android. A list RecyclerViews are items of a parent RecyclerView. The parent RecyclerView with vertical scrolling containing a list of RecyclerViews that are also with vertical scrolling and each of them can be expanded or collapsed.
Dependencies used:
compile 'com.android.support:recyclerview-v7:25.1.0' compile 'com.android.support:cardview-v7:25.1.0' compile 'com.jakewharton:butterknife:7.0.1'
Model classes:
public class Child { String child_name; public Child() {} public String getChild_name() { return child_name; } public void setChild_name(String child_name) { this.child_name = child_name; } }
import java.util.ArrayList; public class ParentChild { ArrayListchild; public ParentChild() {} public ArrayList getChild() { return child; } public void setChild(ArrayList child) { this.child = child; } }
Adapter classes:
import android.os.Handler; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; import com.example.nestedrecyclerview.R; import com.example.nestedrecyclerview.model.Child; import java.util.ArrayList; import butterknife.Bind; import butterknife.ButterKnife; public class ChildAdapter extends RecyclerView.Adapter{ private ArrayList childData; private ArrayList childDataBk; public ChildAdapter(ArrayList childData) { this.childData = childData; childDataBk = new ArrayList<>(childData); } public static class ViewHolder extends RecyclerView.ViewHolder { @Bind(R.id.tv_child) TextView tvChild; @Bind(R.id.iv_expand_collapse_toggle) ImageView tvExpandCollapseToggle; public ViewHolder(View itemView) { super(itemView); ButterKnife.bind(this, itemView); } } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View itemLayoutView = LayoutInflater.from(parent.getContext()) .inflate(R.layout.nested_recycler_item_child, parent, false); ChildAdapter.ViewHolder cavh = new ChildAdapter.ViewHolder(itemLayoutView); return cavh; } final Handler handler = new Handler(); Runnable collapseList = new Runnable() { @Override public void run() { if (getItemCount() > 1) { childData.remove(1); notifyDataSetChanged(); handler.postDelayed(collapseList, 50); } } }; Runnable expandList = new Runnable() { @Override public void run() { int currSize = childData.size(); if (currSize == childDataBk.size()) return; if (currSize == 0) { childData.add(childDataBk.get(currSize)); } else { childData.add(childDataBk.get(currSize)); } notifyDataSetChanged(); handler.postDelayed(expandList, 50); } }; @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) { final ViewHolder vh = (ViewHolder) holder; if (position == 0 && getItemCount() == 1) { vh.tvExpandCollapseToggle.setImageResource(R.drawable.ic_expand_more_white_24dp); vh.tvExpandCollapseToggle.setVisibility(View.VISIBLE); } else if (position == childDataBk.size() - 1) { vh.tvExpandCollapseToggle.setImageResource(R.drawable.ic_expand_less_white_24dp); vh.tvExpandCollapseToggle.setVisibility(View.VISIBLE); } else { vh.tvExpandCollapseToggle.setVisibility(View.GONE); } Child c = childData.get(position); vh.tvChild.setText(c.getChild_name()); vh.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (getItemCount() > 1) { handler.post(collapseList); } else { handler.post(expandList); } } }); } @Override public int getItemCount() { return childData.size(); } }
import android.content.Context; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import com.example.nestedrecyclerview.NestedRecyclerLinearLayoutManager; import com.example.nestedrecyclerview.R; import com.example.nestedrecyclerview.model.Child; import com.example.nestedrecyclerview.model.ParentChild; import java.util.ArrayList; import butterknife.Bind; import butterknife.ButterKnife; public class ParentAdapter extends RecyclerView.Adapter{ ArrayList parentChildData; Context ctx; public ParentAdapter(Context ctx, ArrayList parentChildData) { this.ctx = ctx; this.parentChildData = parentChildData; } public static class ViewHolder extends RecyclerView.ViewHolder { @Bind(R.id.rv_child) RecyclerView rv_child; public ViewHolder(View itemView) { super(itemView); ButterKnife.bind(this, itemView); } } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View itemLayoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.nested_recycler_item_parent, parent, false); ParentAdapter.ViewHolder pavh = new ParentAdapter.ViewHolder(itemLayoutView); return pavh; } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { ViewHolder vh = (ViewHolder) holder; ParentChild p = parentChildData.get(position); initChildLayoutManager(vh.rv_child, p.getChild()); } private void initChildLayoutManager(RecyclerView rv_child, ArrayList childData) { rv_child.setLayoutManager(new NestedRecyclerLinearLayoutManager(ctx)); ChildAdapter childAdapter = new ChildAdapter(childData); rv_child.setAdapter(childAdapter); } @Override public int getItemCount() { return parentChildData.size(); } }
Layouts
activity_main.xml
nested_recycler_item_child.xml
nested_recycler_item_parent
NestedRecyclerLinearLayoutManager.java
import android.content.Context; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.View; import android.view.ViewGroup; /** * http://stackoverflow.com/a/32086918/2069407 */ public class NestedRecyclerLinearLayoutManager extends LinearLayoutManager { private static final String TAG = NestedRecyclerLinearLayoutManager.class.getSimpleName(); public NestedRecyclerLinearLayoutManager(Context context) { super(context); } public NestedRecyclerLinearLayoutManager(Context context, int orientation, boolean reverseLayout) { super(context, orientation, reverseLayout); } private int[] mMeasuredDimension = new int[2]; @Override public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state, int widthSpec, int heightSpec) { final int widthMode = View.MeasureSpec.getMode(widthSpec); final int heightMode = View.MeasureSpec.getMode(heightSpec); final int widthSize = View.MeasureSpec.getSize(widthSpec); final int heightSize = View.MeasureSpec.getSize(heightSpec); int width = 0; int height = 0; for (int i = 0; i < getItemCount(); i++) { measureScrapChild(recycler, i, View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED), mMeasuredDimension); if (getOrientation() == HORIZONTAL) { width = width + mMeasuredDimension[0]; if (i == 0) { height = mMeasuredDimension[1]; } } else { height = height + mMeasuredDimension[1]; if (i == 0) { width = mMeasuredDimension[0]; } } } switch (widthMode) { case View.MeasureSpec.EXACTLY: width = widthSize; case View.MeasureSpec.AT_MOST: case View.MeasureSpec.UNSPECIFIED: } switch (heightMode) { case View.MeasureSpec.EXACTLY: height = heightSize; case View.MeasureSpec.AT_MOST: case View.MeasureSpec.UNSPECIFIED: } setMeasuredDimension(width, height); } private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec, int heightSpec, int[] measuredDimension) { try { View view = recycler.getViewForPosition(0); //fix IndexOutOfBoundsException if (view != null) { RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams(); int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec, getPaddingLeft() + getPaddingRight(), p.width); int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec, getPaddingTop() + getPaddingBottom(), p.height); view.measure(childWidthSpec, childHeightSpec); measuredDimension[0] = view.getMeasuredWidth() + p.leftMargin + p.rightMargin; measuredDimension[1] = view.getMeasuredHeight() + p.bottomMargin + p.topMargin; recycler.recycleView(view); } } catch (Exception e) { e.printStackTrace(); } } }
MainActivity.java
import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import com.example.nestedrecyclerview.adapter.ParentAdapter; import com.example.nestedrecyclerview.model.Child; import com.example.nestedrecyclerview.model.ParentChild; import java.util.ArrayList; /** * Reference * https://github.com/aimanbaharum/RecyclerViewCeption */ public class MainActivity extends AppCompatActivity { private RecyclerView recyclerViewParent; ArrayListparentChildObj; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); recyclerViewParent = (RecyclerView) findViewById(R.id.rv_parent); LinearLayoutManager manager = new LinearLayoutManager(this); manager.setOrientation(LinearLayoutManager.VERTICAL); recyclerViewParent.setLayoutManager(manager); recyclerViewParent.setHasFixedSize(true); ParentAdapter parentAdapter = new ParentAdapter(this, createData()); recyclerViewParent.setAdapter(parentAdapter); } private ArrayList createData() { parentChildObj = new ArrayList<>(); ArrayList list1 = new ArrayList<>(); ArrayList list2 = new ArrayList<>(); ArrayList list3 = new ArrayList<>(); ArrayList list4 = new ArrayList<>(); ArrayList list5 = new ArrayList<>(); for (int i = 0; i < 3; i++) { Child c1 = new Child(); c1.setChild_name("Child 1." + (i + 1)); list1.add(c1); } for (int i = 0; i < 5; i++) { Child c2 = new Child(); c2.setChild_name("Child 2." + (i + 1)); list2.add(c2); } for (int i = 0; i < 2; i++) { Child c3 = new Child(); c3.setChild_name("Child 3." + (i + 1)); list3.add(c3); } for (int i = 0; i < 4; i++) { Child c4 = new Child(); c4.setChild_name("Child 4." + (i + 1)); list4.add(c4); } for (int i = 0; i < 2; i++) { Child c5 = new Child(); c5.setChild_name("Child 5." + (i + 1)); list5.add(c5); } ParentChild pc1 = new ParentChild(); pc1.setChild(list1); parentChildObj.add(pc1); ParentChild pc2 = new ParentChild(); pc2.setChild(list2); parentChildObj.add(pc2); ParentChild pc3 = new ParentChild(); pc3.setChild(list3); parentChildObj.add(pc3); ParentChild pc4 = new ParentChild(); pc4.setChild(list4); parentChildObj.add(pc4); ParentChild pc5 = new ParentChild(); pc5.setChild(list5); parentChildObj.add(pc5); return parentChildObj; } }
Search within Codexpedia
Custom Search
Search the entire web
Custom Search
Related Posts