How to have ListView / RecyclerView inside parent RecyclerView?

I want to add some child views (list items) that come to me from JSON formatted data. Each child list is in the row of the parent list. How can I populate it in a RecyclerView for each item in the row (parent items with child list items)?

I tried using the RecyclerView within the parent line of the RecyclerView (to populate lists of children), but here the child views are not visible.

Parent Adapter Class

 public class DigitizedPrescAdapter extends RecyclerView.Adapter<DigitizedPrescAdapter.ListItemViewHolder>{ private List<PrescriptionModal> prescriptionList; MedicinesInPrescAdapter adapter; public DigitizedPrescAdapter(List<PrescriptionModal> prescriptionListModal) { if (prescriptionListModal == null) { throw new IllegalArgumentException( "PrescriptionList must not be null"); } this.prescriptionList = prescriptionListModal; } @Override public ListItemViewHolder onCreateViewHolder( ViewGroup viewGroup, int viewType) { View itemView = LayoutInflater. from(viewGroup.getContext()). inflate(R.layout.item_row_digitised_request, viewGroup, false); return new ListItemViewHolder(itemView); } @Override public void onBindViewHolder( ListItemViewHolder viewHolder, int position) { PrescriptionModal model = prescriptionList.get(position); viewHolder.prescnum.setText("Prescription "+ ++position); viewHolder.prescNo.setText("Prescription: "+model.getPrescriptionID()); viewHolder.doctorType.setText("Type: "+model.getDoctorType()); viewHolder.doctorName.setText("Doctor: "+model.getDoctorName()); viewHolder.patientName.setText("Patient: "+model.getPatientName()); adapter = new MedicinesInPrescAdapter(model.getLstproduct()); viewHolder.lstMedicines.setAdapter(adapter); } @Override public int getItemCount() { return prescriptionList.size(); } public final static class ListItemViewHolder extends RecyclerView.ViewHolder { TextView prescnum; TextView prescNo; TextView doctorType; TextView patientName; TextView doctorName; CheckBox selectAll; RecyclerView lstMedicines; public ListItemViewHolder(View itemView) { super(itemView); prescnum = (TextView) itemView.findViewById(R.id.prescnum); prescNo = (TextView) itemView.findViewById(R.id.prescNo); doctorType = (TextView) itemView.findViewById(R.id.doctorType); patientName = (TextView) itemView.findViewById(R.id.patientName); doctorName = (TextView) itemView.findViewById(R.id.doctorName); selectAll = (CheckBox) itemView.findViewById(R.id.selectAll); lstMedicines = (RecyclerView) itemView.findViewById(R.id.lstAllMedicines); MyLinearLayoutManager layoutManager = new MyLinearLayoutManager(itemView.getContext(),LinearLayoutManager.VERTICAL,false); lstMedicines.setHasFixedSize(false); lstMedicines.setLayoutManager(layoutManager); } } } 

Adapter class for children

 public class MedicinesInPrescAdapter extends RecyclerView.Adapter<MedicinesInPrescAdapter.MedicineListItemViewHolder>{ List<Modal_Product_List> prescriptionProducts; public MedicinesInPrescAdapter(List<Modal_Product_List> prescriptionListProd) { if (prescriptionListProd == null) { throw new IllegalArgumentException( "PrescriptionProductList must not be null"); } this.prescriptionProducts = prescriptionListProd; } @Override public MedicineListItemViewHolder onCreateViewHolder( ViewGroup viewGroup, int viewType) { View itemView = LayoutInflater. from(viewGroup.getContext()). inflate(R.layout.item_row_medicine_productlist, viewGroup, false); return new MedicineListItemViewHolder(itemView); } @Override public void onBindViewHolder( MedicineListItemViewHolder viewHolder, int position) { Modal_Product_List modelMedicine = prescriptionProducts.get(position); viewHolder.medicineName.setText(modelMedicine.getMedicinename()); viewHolder.medQty.setText(modelMedicine.getQuantity()); viewHolder.days.setText("30"); viewHolder.Amount.setText(modelMedicine.getQuantitybasedprice()); } @Override public int getItemCount() { return prescriptionProducts.size(); } public final static class MedicineListItemViewHolder extends RecyclerView.ViewHolder { TextView medicineName; EditText medQty; TextView days; TextView Amount; CheckBox selectMe; public MedicineListItemViewHolder(View itemView) { super(itemView); medicineName = (TextView) itemView.findViewById(R.id.medicineName); medQty = (EditText) itemView.findViewById(R.id.medQty); days = (TextView) itemView.findViewById(R.id.days); Amount = (TextView) itemView.findViewById(R.id.amount); selectMe = (CheckBox) itemView.findViewById(R.id.selectMe); } } } 
+52
android android-recyclerview
Aug 14 '15 at 2:03
source share
4 answers

I got this problem a few days ago and finally solved it. All you need to do is @override in the layout manager with the onMeasure function , as shown below:

CustomLinearLayoutManager

 public class CustomLinearLayoutManager extends LinearLayoutManager { private static final String TAG = CustomLinearLayoutManager.class.getSimpleName(); public CustomLinearLayoutManager(Context context) { super(context); } public CustomLinearLayoutManager(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(); } } } 

You can simply copy and paste your own layout manager, as described above, and in your reseller’s settings, view in the parent adapter as follows:

 RecyclerView.LayoutManager layoutManager = new CustomLinearLayoutManager(mContext); holder.childRecyclerView.setLayoutManager(layoutManager); 

Remember : do not use the same layoutManager as the parent adapter, otherwise an error will occur.

+55
Aug 19 '15 at 5:05
source share

If I understand, you need a RecyclerView with RecyclerView strings. In this case, I recommend using the extensible RecyclerView using this library . Just follow the extensible example within the link.

There are many more interesting features in the same library, such as Drag and Drop, Swipeable rows ... Watch this video in less than a minute.

You just need to add lib depending on your gradle.build file, for example:

 dependencies { compile 'com.h6ah4i.android.widget.advrecyclerview:advrecyclerview:0.7.4' } 

To be able to import lib in your java files.

+14
Aug 18 '15 at 16:16
source share

According to the Android 23.2 support library from the support library version 23.2.0. So all WRAP_CONTENT should work correctly.

Please update the library version in the Gradle file.

 compile 'com.android.support:recyclerview-v7:23.2.0' 

This allows the RecyclerView size depending on the size of its contents. This means that previously unavailable scripts, such as using WRAP_CONTENT to measure a RecyclerView , are now possible. You will find that all built-in LayoutManager now support automatic measurement

you will need to call setAutoMeasureEnabled(true)

Below is a sample code

 RecyclerView.LayoutManager layout = new LinearLayoutManager(context); layout.setAutoMeasureEnabled(true); 

Since setAutoMeasureEnabled is deprecated, an alternative solution to This method is deprecated at API level 27.1.0. LayoutManager developers should determine if it uses AutoMeasure by overriding isAutoMeasureEnabled() .

+14
Mar 08 '16 at 16:13
source share

Please note: you do not have to create a new adapter every time you call onBindView (), you have to do it once in onCreateView ().

The best way is to use any library, for example - RendererRecyclerViewAdapter

How to add NestedRecyclerView:

Step 1: Add ViewModel to your Modal_Product_List

 public class Modal_Product_List implements ViewModel { String getMedicinename() { ... } //your method int getQuantity() { ... } //your method int getQuantitybasedprice() { ... } //your method } 

Step 2: Create a ViewBinder for Modal_Product_List :

 private ViewRenderer getModalProductViewRenderer() { return new ViewBinder<>( R.layout.item_row_medicine_productlist, //your child layout id Modal_Product_List.class //your child item class (model, finder, payloads) -> finder .setText(R.id.medicineName, model.getMedicinename()) .setText(R.id.medQty, (String) model.getQuantity()) .setText(R.id.amount, (String) model.getQuantitybasedprice()) .setChecked(R.id.selectMe, ...) ); } 

Step 3: Add the CompositeViewModel interface to PrescriptionModal or from DefaultCompositeModel :

 public class PrescriptionModal extends DefaultCompositeViewModel { String getPrescriptionID() {...} //your method String getDoctorType() {...} //your method String getDoctorName() {...} //your method String getPatientName() {...} //your method @Override List<Modal_Product_List> getItems() { return yourProductItems; } } 

Step 4: Create a ViewBinder for PrescriptionModal :

 private ViewRenderer getModalProductViewRenderer() { return new CompositeViewBinder<>( R.layout.item_row_digitised_request, //your parent item layout R.id.lstAllMedicines, //your nested RecyclerView PrescriptionModal.class, //your parent item class (model, finder, payloads) -> finder //no need to set child items, it will set automatically .setText(R.id.prescnum, "Prescription:" + model.getPrescriptionID) .setText(R.id.doctorName, "Doctor:" + model.getDoctorName()) .setText(R.id.doctorType, "Type:" + model.getDoctorType()) .setText(R.id.patientName, "Patient:" + model.getPatientName()) ).registerRenderer(getModalProductViewRenderer()); //register ModalProductViewRenderer .registerRenderer(...) //if you need you can create other renderer and register here ); 

Step 5 (optional): If you need a custom LayoutManager , then extend the CompositeViewBinder and override the createLayoutManager method and use it instead of the CompositeViewBinder

 public class CustomCompositeViewBinder extends CompositeViewBinder { //... @Override protected RecyclerView.LayoutManager createLayoutManager() { return new MyLinearLayoutManager(getContext(), VERTICAL, false); } } 

Step 6: Initialize the RendererRecyclerViewAdapter and the registration handler:

 RendererRecyclerViewAdapter adapter = new RendererRecyclerViewAdapter(getContext()); recyclerView.setAdapter(adapter); adapter.registerRenderer(getModalProductViewRenderer()); adapter.registerRenderer(...); //if you need you can create other renderers adapter.setItems(getPrescriptionListModal()); 

This is a very short and easy way to add a Nested RecyclerView.

0
Jan 26 '18 at 16:01
source share



All Articles