6

I have created expandable recycle view in my app looks like below

It has parent Items Menu category and Category has child items as shown in image

enter image description here

Following is part of my parent adapter code.

 public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
    if (i > HEADER_COUNT - 1) {
        FoodMenuItem foodMenuItem = foodMenuItems.get(i - HEADER_COUNT);
        MenuViewHolder menuViewHolder = (MenuViewHolder) viewHolder;
        //menuViewHolder.rvMenu.setLayoutManager(new LinearLayoutManager(viewHolder.itemView.getContext(), LinearLayoutManager.VERTICAL, false));
        if (isVegOnly) {
            List<Item> items = new ArrayList<>();
            for (Item item : foodMenuItem.getItems()) {
                if (item.getType().equalsIgnoreCase(Item.FOOD_TYPE_VEG)) {
                    items.add(item);
                }
            }
            menuViewHolder.rvMenu.setAdapter(new FoodMenuChildRecycler(items, foodMenuParentListener, i, isAddAllowed));
            menuViewHolder.tvNumItems.setText("(" + items.size() + " items)");

        } else {
            menuViewHolder.rvMenu.setAdapter(new FoodMenuChildRecycler(foodMenuItem.getItems(), foodMenuParentListener, i, isAddAllowed));
            menuViewHolder.tvNumItems.setText("(" + foodMenuItem.getItems().size() + " items)");

        }
        menuViewHolder.ivArrow.setVisibility(menuViewHolder.rvMenu.getAdapter().getItemCount() > 0 ? View.VISIBLE : View.GONE);
        menuViewHolder.ivArrow.setImageResource(foodMenuItem.isExpanded() ? R.drawable.chev_up : R.drawable.chev_down);
        menuViewHolder.tvTitle.setText(foodMenuItem.getCategoryName());
        menuViewHolder.rvMenu.setNestedScrollingEnabled(false);
        if (foodMenuItem.isExpanded()) {
            menuViewHolder.rvMenu.setVisibility(View.VISIBLE);
        } else {
            menuViewHolder.rvMenu.setVisibility(View.GONE);
        }
    }

}

Following is code for child adapter onBindViewHolder

  public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
    ChildMenuHolder childMenuHolder = (ChildMenuHolder) viewHolder;
    Context context = viewHolder.itemView.getContext();
    Item item = itemList.get(i);
    childMenuHolder.tvTitle.setText(item.getTitle());
    childMenuHolder.txtQty.setText(String.valueOf(item.getQuatity()));
    childMenuHolder.txtCartInc.setVisibility(item.isAddedToCart() ? View.VISIBLE : View.GONE);
    childMenuHolder.txtQty.setVisibility(item.isAddedToCart() ? View.VISIBLE : View.GONE);
    childMenuHolder.txtCartDec.setVisibility(item.isAddedToCart() ? View.VISIBLE : View.GONE);
    childMenuHolder.btnAdd.setVisibility(!item.isAddedToCart() ? View.VISIBLE : View.GONE);
    childMenuHolder.btnAdd.setBackgroundResource(isAddAllowed ? R.drawable.rounded_bottom_edge_shape_food : R.drawable.rounded_bottom_edge_shape_disable);
    childMenuHolder.btnAdd.setTextColor(isAddAllowed ? ContextCompat.getColor(context, R.color.button_green) : ContextCompat.getColor(context, R.color.gray_a1));
    childMenuHolder.ivType.setColorFilter(item.getType().equalsIgnoreCase(Item.FOOD_TYPE_VEG) ? ContextCompat.getColor(context, R.color.selected_green) : ContextCompat.getColor(context, R.color.app_red));
}

Following code inside Parent adapter to expand & collapse

  public MenuViewHolder(@NonNull View itemView) {
        super(itemView);
        tvTitle = (TextView) itemView.findViewById(R.id.tvTitle);
        tvNumItems = (TextView) itemView.findViewById(R.id.tvNumItems);
        ivArrow = (ImageView) itemView.findViewById(R.id.ivArrow);
        rvMenu = (RecyclerView) itemView.findViewById(R.id.rvMenu);
        rvMenu.setLayoutManager(new LinearLayoutManager(itemView.getContext()));
       // rvMenu.setNestedScrollingEnabled(false);
        rlArrow = itemView.findViewById(R.id.rlArrow);
        rlArrow.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (foodMenuParentListener != null) {
                    foodMenuParentListener.OnExpandClick(getAdapterPosition());
                }
            }
        });
        tvTitle.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (foodMenuParentListener != null) {
                    foodMenuParentListener.OnExpandClick(getAdapterPosition());
                }
            }
        });
    }

onExpandClick inside listener is as below

        @Override
        public void OnExpandClick(int position) {
            FoodMenuRecyclerAdapter foodMenuRecyclerAdapter = (FoodMenuRecyclerAdapter) recyclerView.getAdapter();
            foodMenuRecyclerAdapter.setExpandIndex(position);
            foodMenuRecyclerAdapter.notifyItemChanged(position);
        }

setExpandIndex inside adapter as below

public void setExpandIndex(int expandIndex) {
    foodMenuItems.get(expandIndex - HEADER_COUNT).setExpanded(!foodMenuItems.get(expandIndex - HEADER_COUNT).isExpanded());
}

Since there are too many items in ChildRecycler adapter I facing a big lag issue when there are too many child items. It works properly when number of child items is less

How to fix this?

Also I am finding it difficult to have single recycler view due to presence cardview in background as shown in image otherwise I would have used single recycler view and for collapse/expand would have implemented add and remove items at a position

New Note: Date 5 May

New solution I tried using NestedScrollView and then added recycler views to this nested RecyclerView

Following is code

 for (FoodMenuItem item : foodResult.getFoodMenuItems()) {
            View view = LayoutInflater.from(getContext()).inflate(R.layout.layout_food_parent, llMenu, false);
            RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.rvMenu);
            ((TextView)view.findViewById(R.id.tvtitle)).setText(item.getCategoryName());

            recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
            view.findViewById(R.id.rlArrow).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    recyclerView.setVisibility(recyclerView.getVisibility() == View.VISIBLE ? View.GONE : View.VISIBLE);
                }
            });
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    recyclerView.setAdapter(new FoodMenuChildRecycler(item.getItems(), getAddItemListener(), i, isFlightAssociatedWithLocation));
                    llMenu.addView(view);
                }
            }, 200);


            i++;

        }

Following is XML code

 <android.support.v4.widget.NestedScrollView
        android:id="@+id/rvParentMenu"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clipToPadding="false"
        android:paddingBottom="160dp">

        <LinearLayout
            android:id="@+id/llMenu"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical" />

    </android.support.v4.widget.NestedScrollView>

Issue I am facing is code to add views to linear layout inside nested scroll view and set adapter call for recycler views is freezing UI almost for few seconds added handler for it but does not seem to a nice solution

amodkanthe
  • 4,119
  • 4
  • 27
  • 55
  • Take a look at this: https://github.com/aminography/PrimeAdapter – aminography May 03 '19 at 06:18
  • Any other way to do it without library? – amodkanthe May 03 '19 at 06:27
  • the leak is caused by the lack of recycling on your child views, you have to create a recyclerView with two viewType( header, child) when detect header clic, execute collapse/ expand by removing or adding child item on the correct position...So to resolve the issue you have to create a single List for header and child. – Anis BEN NSIR May 03 '19 at 15:42
  • Yeah problem is as shown in image I have to show parent category name and child items in same card which is difficult to implement and there are more than categories with child items – amodkanthe May 03 '19 at 18:14
  • @Anis BEN NSIR updated image please check – amodkanthe May 03 '19 at 19:13
  • thanks for the image, it still same, if you need to group them by CardView, you can refer here: https://stackoverflow.com/questions/31273203/what-is-the-best-practice-to-group-items-into-cardview – Anis BEN NSIR May 06 '19 at 08:29
  • Can you share your code please? – Rahul Shukla May 07 '19 at 10:43
  • Shared all required code already – amodkanthe May 07 '19 at 14:34
  • 1
    I believe that there's no good answer here. The fact of the matter is that you've designed an app that requires the inflation of hundreds of views when the user taps something, and that is always going to be "too slow". I think you will have to change your app design (maybe only load five children at a time when the user expands a section, and add a "load five more" button at the bottom). You could look into using a shared recycled view pool for the child adapters, but that won't solve the lag the very first time the user expands a section with hundreds of children. – Ben P. May 07 '19 at 19:19
  • tried another way to do it but app is crashing on notifyItemRangeRemoved following is link to question https://stackoverflow.com/questions/56311835/custom-expandable-recyclerview-crashing-on-notifyitemrangeremoved?noredirect=1#comment99233499_56311835 – amodkanthe May 26 '19 at 08:47

0 Answers0