usar tutorial studio recyclerview recycler personalizado libreria entre diferencias cuando card and android android-recyclerview

android - tutorial - ¿Cómo tener un ListView/RecyclerView dentro de un RecyclerView padre?



recyclerview personalizado (4)

Por Android Support Library 23.2 de una biblioteca de soporte versión 23.2.0. Por lo tanto, todo WRAP_CONTENT debería funcionar correctamente.

Actualice la versión de una biblioteca en el archivo gradle .

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

Esto permite que un RecyclerView dimensione en función del tamaño de su contenido. Esto significa que los escenarios previamente no disponibles, como el uso de WRAP_CONTENT para una dimensión de RecyclerView , ahora son posibles. Encontrarás que todos los LayoutManagers integrados ahora admiten la medición automática.

deberás llamar a setAutoMeasureEnabled(true)

A continuación se muestra el código de muestra

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

Como setAutoMeasureEnabled es una solución alternativa en desuso Este método fue en desuso en el nivel API 27.1.0. Los implementadores de LayoutManager deben definir si utiliza o no AutoMeasure anulando isAutoMeasureEnabled() .

Quiero agregar algunas vistas secundarias (elementos de lista), que me llegan de datos con formato JSON. Cada lista secundaria está debajo de una fila de elementos de la lista principal. ¿Cómo puedo completarlo en RecyclerView para cada elemento de la fila (elementos principales con elementos de la lista secundaria)?

He intentado usar RecyclerView dentro de la fila padre RecyclerView (para llenar listas secundarias), pero aquí las vistas secundarias no son visibles.

Clase de adaptador principal

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); } } }

Clase de adaptador para niños

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); } } }


Recibí este problema hace unos días y finalmente lo resolví. Todo lo que tiene que hacer es anular la función onMeasure del administrador de diseño de la siguiente manera:

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(); } } }

Puede copiar y pegar el administrador de diseño personalizado como se indica arriba y configurar su vista de reciclador en el adaptador principal de esta manera:

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

Recuerde : no utilice el mismo layoutManager que el adaptador principal, o se producirá un error.


Si entiendo, quieres un RecyclerView con filas RecyclerView. En este caso, le recomiendo que use un RecyclerView expandible , usando esta lib . Simplemente siga el ejemplo expandible dentro del enlace.

Hay muchas más funciones interesantes en la misma biblioteca, como arrastrar y soltar, filas deslizables ... Mira este video de ejemplo de menos de un minuto.

Solo tiene que agregar la biblioteca a las dependencias en su archivo gradle.build , como sigue:

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

Para poder import la lib en sus archivos java.


Tenga en cuenta: no debe crear un nuevo adaptador cada vez que llame a onBindView (), debe hacerlo una vez en onCreateView ().

La mejor manera - para usar cualquier biblioteca, por ejemplo - RendererRecyclerViewAdapter

Cómo agregar un NestedRecyclerView:

Paso 1: Agregue la interfaz ViewModel a su Modal_Product_List

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

Paso 2: Cree un ViewBinder para la 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, ...) ); }

Paso 3: Agregue la interfaz CompositeViewModel a PrescriptionModal o extienda desde 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; } }

Paso 4: Cree un ViewBinder para el 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 );

Paso 5 (Opcional): si necesita un LayoutManager personalizado, extienda CompositeViewBinder y anule el método createLayoutManager y createLayoutManager en lugar de CompositeViewBinder

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

Paso 6: Inicialice RendererRecyclerViewAdapter y registre el renderizador:

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

Es una forma realmente corta y simple de agregar un RecyclerView anidado