Nested / child RecyclerViews inside parent RecyclerView with custom LinearLayoutManager not working properly

I tried after this SO answers about how to use a custom LinearLayoutManager , but my nested RecyclerView does not display at all.

Parent RecyclerView in action:

  RecyclerView detailsRecyclerView = (RecyclerView) dialog.findViewById(R.id.category_dish_dialog_recycler_view); detailsRecyclerView.setHasFixedSize(true); LinearLayoutManager layoutManager = new LinearLayoutManager(CategoryActivity.this); layoutManager.setOrientation(LinearLayoutManager.VERTICAL); detailsRecyclerView.setLayoutManager(layoutManager); DishDetailsAdapter detailsAdapter = new DishDetailsAdapter(dish.getDishOptions(), CategoryActivity.this); detailsRecyclerView.setAdapter(detailsAdapter); detailsAdapter.notifyDataSetChanged(); 

Adapter for viewing parent recycler:

Note that the child / nested RecyclerView is inside the OptionsViewHolder :

 public class DishDetailsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private List<DishOption> options; private Context context; private SharedData sharedData = SharedData.getInstance(); public DishDetailsAdapter(List<DishOption> detailsList, Context parentContext) { options = detailsList; context = parentContext; sharedData.setMainFont(context); sharedData.setSecondaryFont(context); } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { LayoutInflater inflater = LayoutInflater.from(parent.getContext()); View view = inflater.inflate(R.layout.category_dish_dialog_option, parent, false); RecyclerView.ViewHolder viewHolder = new OptionsViewHolder(view); return viewHolder; } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { DishOption dishOption = options.get(position); OptionsViewHolder vh = (OptionsViewHolder) holder; vh.optionName.setText(dishOption.getTitle()); vh.optionName.setTypeface(sharedData.getSecondaryFont()); List<DishOptionItem> dishOptionItems = dishOption.getItems(); ItemsAdapter itemsAdapter = new ItemsAdapter(dishOptionItems, context); //NOTICE CHILD/NESTED RECYCLER VIEW HERE!!!!!!!!!!!!!!!!!!!!!!! vh.nestedRecyclerView.setAdapter(itemsAdapter); itemsAdapter.notifyDataSetChanged(); LinearLayoutManager layoutManager = new NestedLinearLayoutManager(context, LinearLayoutManager.VERTICAL, false); vh.nestedRecyclerView.setLayoutManager(layoutManager); } @Override public int getItemCount() { return options.size(); } /** * View holders for dish options Options */ public class OptionsViewHolder extends RecyclerView.ViewHolder { private TextView optionName; private RecyclerView nestedRecyclerView; public OptionsViewHolder(View itemView) { super(itemView); optionName = (TextView) itemView.findViewById(R.id.dish_dialog_option_title); nestedRecyclerView = (RecyclerView) itemView.findViewById(R.id.category_nested_recycler_view); } } } 

RecyclerView child / nested adapter:

 public class ItemsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private List<DishOptionItem> items; private Context context; private SharedData sharedData = SharedData.getInstance(); public ItemsAdapter(List<DishOptionItem> itemsList, Context parentParentContext) { items = itemsList; context = parentParentContext; } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { LayoutInflater inflater = LayoutInflater.from(parent.getContext()); View view = inflater.inflate(R.layout.category_dish_dialog_item, parent, false); RecyclerView.ViewHolder viewHolder = new ItemViewHolder(view); return viewHolder; } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { DishOptionItem item = items.get(position); ItemViewHolder iVH = (ItemViewHolder) holder; iVH.itemName.setText(item.getName()); } @Override public int getItemCount() { return items.size(); } /** * View holders for dish options Items */ public class ItemViewHolder extends RecyclerView.ViewHolder { private TextView itemName; private TextView itemPrice; public ItemViewHolder(View itemView) { super(itemView); itemName = (TextView) itemView.findViewById(R.id.dish_dialog_item_name); //itemPrice = (TextView) itemView.findViewById(R.id.dish_dialog_item_price); } } } 

Finally, the custom LinearLayoutManager:

 public class NestedLinearLayoutManager extends LinearLayoutManager { public NestedLinearLayoutManager(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]; } } } // If child view is more than screen size, there is no need to make it wrap content. We can use original onMeasure() so we can scroll view. if (height < heightSize && width < widthSize) { 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); } else { super.onMeasure(recycler, state, widthSpec, heightSpec); } } private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec, int heightSpec, int[] measuredDimension) { View view = recycler.getViewForPosition(position); // For adding Item Decor Insets to view super.measureChildWithMargins(view, 0, 0); if (view != null) { RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams(); int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec, getPaddingLeft() + getPaddingRight() + getDecoratedLeft(view) + getDecoratedRight(view), p.width); int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec, getPaddingTop() + getPaddingBottom() + getPaddingBottom() + getDecoratedBottom(view) , p.height); view.measure(childWidthSpec, childHeightSpec); // Get decorated measurements measuredDimension[0] = getDecoratedMeasuredWidth(view) + p.leftMargin + p.rightMargin; measuredDimension[1] = getDecoratedMeasuredHeight(view) + p.bottomMargin + p.topMargin; recycler.recycleView(view); } } } 

If someone thinks they need to see the xml layout files, I can post them here. Please help, I do not know what else to try.

+5
source share

Source: https://habr.com/ru/post/1235371/


All Articles