ProgramingTip

부모 RecyclerView 안에있는 방법은 무엇입니까?

bestdevel 2021. 1. 7. 21:26
반응형

부모 RecyclerView 안에있는 방법은 무엇입니까?


JSON 형식의 데이터에서 나에게 오는 일부 하위 뷰 (목록 항목)를 추가하고 싶습니다. 각 하위 목록은 상위 목록 항목 행 아래에 있습니다. RecyclerView각 행 항목 (하위 목록 항목이있는 상위 항목) 대해 어떻게 채울 수 있습니까?

부모 행 (하위 목록 채우기 용) RecyclerView내에서 사용을 시도 했지만 여기에서는 사용을 RecyclerView표시하지 않았습니다.

상위 어댑터 클래스

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

며칠 전에 문제가 발생하여 마침내 해결되었습니다. onMeasure의 @Override 다음과 같은 기능이있는 레이아웃 매니저 입니다 .

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

위와 같이 사용자 정의 레이아웃 관리자를 복사하여 배치하고 다음과 같이 상위 어댑터에서 recyclerview를 수 있습니다.

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

알아 두기 : 상위 어댑터와 동일한 layoutManager를 사용하지 마십시오. 그렇지 않으면 오류가 발생합니다.


내가 이해한다면 RecyclerView 행이있는 RecyclerView를 원합니다. 이 경우 나는 당신이 사용하는 것이 좋습니다 확장 RecyclerView을 사용하여, 이 lib 디렉토리 . 링크 내 에서 확장 가능한 예를 따르십시오 .

드래그 앤 드롭, 스 와이프 가능한 행과 같은 더 많은 멋진 기능이 동일한 라이브러리에 있습니다. 1 분도 채 안되는 예제 동영상을 시청 하세요 .

gradle.build다음과 같이 파일 의 종속성에 lib를 추가하기 만하면됩니다 .

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

importJava 파일에서 lib 를 사용할 수 있습니다.


으로 안드로이드 지원 라이브러리 23.2 지원 라이브러리 버전 23.2.0의. 따라서 모두 WRAP_CONTENT올바르게 작동해야합니다.

gradle 파일 에서 라이브러리 버전을 업데이트 하십시오.

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

이를 통해 RecyclerView콘텐츠의 크기에 따라 자체 크기를 조정할 수 있습니다 . 이는 WRAP_CONTENT의 차원에 사용 하는 것과 같이 이전에 사용할 수 없었던 시나리오 RecyclerView가 이제 가능하다는 것을 의미합니다. 이제 모든 내장 LayoutManager가 자동 측정을 지원함을 알 수 있습니다.

당신은 전화해야 할 것입니다 setAutoMeasureEnabled(true)

아래는 샘플 코드입니다.

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

으로 setAutoMeasureEnabled대체 솔루션이되지 않습니다이 메소드는 API 레벨 27.1.0을 사용합니다. 의 구현 LayoutManager자는을 재정 의하여 AutoMeasure를 사용할지 여부를 정의해야합니다 isAutoMeasureEnabled().


참고 : onBindView ()를 호출 할 때마다 새 Adapter를 만들지 말고 onCreateView ()에서 한 번만 수행해야합니다.

가장 좋은 방법-모든 라이브러리를 사용하는 것 (예 : RendererRecyclerViewAdapter)

NestedRecyclerView를 추가하는 방법 :

1 단계 :ViewModel 인터페이스 추가Modal_Product_List

public class Modal_Product_List implements ViewModel {

    String getMedicinename() { ... } //your method
    int getQuantity() { ... } //your method
    int getQuantitybasedprice() { ... } //your method
}

2 단계 :ViewBinder대한 만들기 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, ...)
    );
}

3 단계 : 다음에서 CompositeViewModel인터페이스 추가 PrescriptionModal또는 확장 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; }
}

4 단계 :ViewBinder대한 만들기 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
);

5 단계 (선택 사항) : Custom이 필요한 경우 메서드 LayoutManager를 확장 CompositeViewBinder하고 재정의하고 createLayoutManager대신 사용합니다.CompositeViewBinder

public class CustomCompositeViewBinder extends CompositeViewBinder {

    //...

    @Override
    protected RecyclerView.LayoutManager createLayoutManager() {
        return new MyLinearLayoutManager(getContext(), VERTICAL, false);
    }
}

6 단계 :RendererRecyclerViewAdapter 렌더러 초기화 및 등록 :

RendererRecyclerViewAdapter adapter = new RendererRecyclerViewAdapter(getContext());
recyclerView.setAdapter(adapter);

adapter.registerRenderer(getModalProductViewRenderer());
adapter.registerRenderer(...); //if you need you can create other renderers

adapter.setItems(getPrescriptionListModal());

Nested RecyclerView를 추가하는 정말 짧고 간단한 방법입니다.

참조 URL : https://stackoverflow.com/questions/32011995/how-to-have-a-listview-recyclerview-inside-a-parent-recyclerview

반응형