Je souhaite ajouter des vues enfant (éléments de liste) qui me proviennent de données au format JSON. Chaque liste d'enfants se trouve sous une ligne d'élément de liste parent. Comment puis-je le renseigner dans RecyclerView
pour chaque élément de ligne (éléments parents avec des éléments de liste enfant)?
J'ai essayé d'utiliser RecyclerView
dans RecyclerView
ligne parent (pour remplir des listes enfants), mais dans ce cas, les vues enfant ne sont pas visibles.
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);
}
}
}
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);
}
}
}
J'ai eu ce problème il y a quelques jours et l'ai finalement résolu. Tout ce que vous avez à faire est @ remplacez le gestionnaire de disposition onMeasure comme ci-dessous:
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();
}
}
}
Vous pouvez simplement copier et coller le gestionnaire de disposition personnalisé comme ci-dessus et configurer votre vue de recyclage dans l'adaptateur parent de la manière suivante:
RecyclerView.LayoutManager layoutManager = new CustomLinearLayoutManager(mContext);
holder.childRecyclerView.setLayoutManager(layoutManager);
Rappelez-vous: N'utilisez pas le même layoutManager comme adaptateur parent, sinon une erreur se produira.
Si je comprends bien, vous voulez un RecyclerView avec des lignes RecyclerView. Dans ce cas, je vous recommande d'utiliser un extensible RecyclerView , en utilisant this lib . Il suffit de suivre le exemple extensible dans le lien.
Il y a beaucoup d'autres fonctionnalités intéressantes dans la même bibliothèque, comme le glisser-déposer, les rangées balayables ... Regardez ceci moins d'une minute exemple de vidéo .
Vous devez juste ajouter la bibliothèque aux dépendances dans votre gradle.build
fichier, comme suit:
dependencies {
compile 'com.h6ah4i.Android.widget.advrecyclerview:advrecyclerview:0.7.4'
}
Pour pouvoir import
la lib dans vos fichiers Java.
Par Android Support Library 23.2 d’une version de la bibliothèque d’assistance 23.2.0. Donc, tout WRAP_CONTENT
Devrait fonctionner correctement.
Veuillez mettre à jour la version d'une bibliothèque dans le fichier gradle.
compile 'com.Android.support:recyclerview-v7:23.2.0'
Cela permet à un RecyclerView
de se redimensionner lui-même en fonction de la taille de son contenu. Cela signifie que des scénarios précédemment indisponibles, tels que l'utilisation de WRAP_CONTENT
Pour une dimension de RecyclerView
, sont désormais possibles. Vous constaterez que tous les gestionnaires de mises en forme intégrés prennent désormais en charge la mesure automatique.
vous devrez appeler setAutoMeasureEnabled(true)
Ci-dessous l'exemple de code
RecyclerView.LayoutManager layout = new LinearLayoutManager(context);
layout.setAutoMeasureEnabled(true);
As setAutoMeasureEnabled
est obsolète. Solution alternative Cette méthode est obsolète en API niveau 27.1.0. Les développeurs de LayoutManager
doivent définir s'ils utilisent ou non AutoMeasure en remplaçant isAutoMeasureEnabled()
.
Remarque: vous ne devez pas créer de nouvel adaptateur chaque fois que vous appelez onBindView (), vous devez le faire une fois dans onCreateView ().
La meilleure méthode - pour utiliser n'importe quelle bibliothèque, par exemple - RendererRecyclerViewAdapter
Comment ajouter un NestedRecyclerView:
Étape 1: Ajoutez l'interface ViewModel
à votre Modal_Product_List
public class Modal_Product_List implements ViewModel {
String getMedicinename() { ... } //your method
int getQuantity() { ... } //your method
int getQuantitybasedprice() { ... } //your method
}
Étape 2: Créez un ViewBinder
pour le 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, ...)
);
}
Étape 3: Ajoutez l'interface CompositeViewModel
à PrescriptionModal
ou étendez de 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; }
}
Étape 4: Créez un ViewBinder
pour le 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
);
Étape 5 (facultatif): Si vous avez besoin d'un Custom LayoutManager
, étendez le CompositeViewBinder
et remplacez le createLayoutManager
méthode et l'utiliser à la place de CompositeViewBinder
public class CustomCompositeViewBinder extends CompositeViewBinder {
//...
@Override
protected RecyclerView.LayoutManager createLayoutManager() {
return new MyLinearLayoutManager(getContext(), VERTICAL, false);
}
}
Étape 6: Initialisez RendererRecyclerViewAdapter
et enregistrez le rendu:
RendererRecyclerViewAdapter adapter = new RendererRecyclerViewAdapter(getContext());
recyclerView.setAdapter(adapter);
adapter.registerRenderer(getModalProductViewRenderer());
adapter.registerRenderer(...); //if you need you can create other renderers
adapter.setItems(getPrescriptionListModal());
C'est un moyen très simple et rapide pour ajouter un Nested RecyclerView