Come avere una ListView/RecyclerView all’interno di un genitore RecyclerView?

Vorrei aggiungere alcune Viste figlio (Voci di Elenco), che mi giungono da dati in formato JSON. Ogni bambino lista è in un elenco padre elemento di riga. Come posso compilarlo in RecyclerView per ogni riga articolo (gli articoli Padre con figlio voci di elenco)?

Ho provato con RecyclerView entro RecyclerView riga padre (per la compilazione di elenchi secondari), ma qui viste figlio non sono visibili.

Genitore Classe Adattatore

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

Bambino Adattatore Classe

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);
        }
    }
}
Tenta Expandablelistviewmettere il genitore dell’intestazione e del bambino, la sua vista.

OriginaleL’autore Ravi Kabra | 2015-08-14

4 risposte

  1. 53

    Ho avuto questo problema qualche giorno fa e finalmente risolto. Tutto quello che dovete fare è @override del layout manager onMeasure funzione come di seguito:

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

    Si può semplicemente copia e passato il gestore di layout personalizzato come sopra, e impostare il vostro recyclerview nel genitore adattatore come questo:

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

    Ricordare : non usare la stessa layoutManager come genitore adattatore, o errore.

    Grazie pptang, funziona benissimo, ma l’altezza è ancora un problema, se provo a scorrere, alcuni bambini perdono la loro visibilità e anche io ho alcuni edittexts in righe. Quindi ho bisogno che i loro dati non devono essere persi durante lo scorrimento..
    Ma cosa succede se nidificata RecyclerView ha un imprevedibile quantità di elementi? Quindi ogni volta che questo RecyclerView mostra ha il padre RecyclerView fila, avrà un’altezza diversa.
    So che cosa si sta dicendo. Funziona ancora in questo caso. Qualche problema si è verificato durante il tuo stavano cercando?
    ho fatto come mi hai suggerito ho perso gli elementi di seguito il bambino riciclatore di vista cosa devo fare ?
    mandami il tuo snippet di codice e mi può aiutare a risolvere il problema. La mia casella di posta: [email protected]

    OriginaleL’autore pptang

  2. 14

    Da Android Support Library 23.2 di una libreria di supporto versione 23.2.0. Così tutti WRAP_CONTENT dovrebbe funzionare correttamente.

    Si prega di aggiornare la versione di una libreria in gradle file.

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

    Questo permette un RecyclerView a misura in base alla dimensione del suo contenuto. Questo significa che in precedenza non disponibile scenari, come l’utilizzo di WRAP_CONTENT per una dimensione di RecyclerViewsono ora possibili. Troverai tutti costruiti in LayoutManagers ora supportano l’auto-misurazione.

    ti verrà richiesto di chiamare setAutoMeasureEnabled(true)

    Di seguito è il codice di esempio

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

    Come setAutoMeasureEnabled è deprecato soluzione alternativa
    Questo metodo è stato sconsigliato a livello API 27.1.0. Implementors di LayoutManager dovrebbe definire se non si utilizza AutoMeasure sovrascrivendo isAutoMeasureEnabled().

    setAutoMeasureEnabled dovrebbe essere chiamato su che cosa?
    LayoutManager. RecyclerView.LayoutManager layout = new LinearLayoutManager(context); layout.setAutoMeasureEnabled(true);
    giusto @LuccasClezar
    vedo automeasureenabled è deprecato. ma che cosa allora ? io non vedo alcuna sostituzione menzionato
    come per la documentazione ignorare il LayoutManager e impostare isAutoMesure per vero

    OriginaleL’autore Maheshwar Ligade

  3. 13

    Se ho ben capito, vuoi un RecyclerView con RecyclerView righe.
    In questo caso vi consiglio di utilizzare un espandibile RecyclerView, utilizzando questo lib. Basta seguire le espandibile esempio all’interno del collegamento.

    Ci sono molte altre funzioni interessanti nella stessa cartella lib, come il Drag and Drop, Swipeable righe… Guarda questo meno di un minuto video di esempio.

    Basta aggiungere la lib per le dipendenze gradle.build file, come riportato di seguito:

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

    Per essere in grado di import lib nel file java.

    ehi Geraldo sto cercando di utilizzare questo lib e appena notato che dice: “Se si utilizza la libreria di supporto v23.0.x, si prega di utilizzare v0.8.1, invece.” Nel mio dipendenze ho compile 'com.android.support:recyclerview-v7:23.0.0'compile 'com.android.support:cardview-v7:23.0.0' e compile 'com.android.support:appcompat-v7:23.0.0' devo cambiare questo?

    OriginaleL’autore Geraldo Neto

  4. 0

    Si prega di notare: non si deve creare nuova Scheda ogni volta che si chiama onBindView(), si dovrebbe fare una volta nella onCreateView().

    Il Modo Migliore per utilizzare qualsiasi libreria, per esempio – RendererRecyclerViewAdapter

    Come aggiungere un NestedRecyclerView:

    Passo 1: Aggiungere il ViewModel interfaccia Modal_Product_List

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

    Passo 2: Creare un ViewBinder per il 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, ...)
        );
    }

    Passo 3: Aggiungere il CompositeViewModel interfaccia PrescriptionModal o estendere da 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; }
    }

    Passo 4: Creare un ViewBinder per il 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
    );

    Passo 5(Opzionale): Se avete bisogno di un Personalizzato LayoutManagerquindi estendere il CompositeViewBinder e ignorare il createLayoutManager metodo e utilizzare invece di CompositeViewBinder

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

    Passo 6: Inizializzare RendererRecyclerViewAdapter e registrare renderer:

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

    È molto breve e semplice modo per aggiungere un Nidificati RecyclerView

    OriginaleL’autore Vitaly

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *