7

Here is my current code. I want to hide a specific item on my recyclerview but when I use visibility.gone still occupies spaces on the recyclerview. I also tried all the possible solutions How to hide an item from Recycler View on a particular condition? Any help

  for(int j =0; j < minusList.size(); j++){
      int availableRooms =  minusList.get(j);

      if(norooms > availableRooms){ //norooms is the number of rooms wanted
      holder.itemView.setVisibility(View.GONE);
      mAdapter.notifyItemRemoved(position);
     }else{
      holder.rRoomsLeft.setText("Room available");
     }

}

Here is my XML

<android.support.v7.widget.RecyclerView
                android:id="@+id/listView"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:focusable="false"
                android:focusableInTouchMode="false" />
nani10
  • 301
  • 4
  • 9
  • Better post your recycler item cell XML code – Dhaval Solanki Mar 12 '19 at 07:24
  • @DhavalSolanki Edited my post – nani10 Mar 12 '19 at 07:30
  • Actually, I ask for cell XML, means layout which you used for show single row. – Dhaval Solanki Mar 12 '19 at 07:36
  • What is the use of `holder.itemView.setVisibility(View.GONE);` is you are calling `notifyItemRemoved` ?. If item get Removed then its visibility does not matter .,.. Also i have no idea where exactly you are calling this piece of code . Provide a [mcve]. – ADM Mar 12 '19 at 07:40
  • If I put my whole code it's too many If you want every detail lol. – nani10 Mar 12 '19 at 07:44
  • I'll remove `notifyItemRemoved` I just want to remove the space using `visibility(GONE)` – nani10 Mar 12 '19 at 07:45
  • That's the simpliest and smaller lol – nani10 Mar 12 '19 at 07:56
  • Can you include screenshots of the recyclerview before and after hiding item? – MD Naseem Ashraf Mar 12 '19 at 08:02
  • I think you are using the padding or margin in the XML row file that's why its showing blank space. – raj kavadia Mar 12 '19 at 08:33
  • you want to hide a row but don't want to delete the item from the list ?? – Shahadat Hossain Shaki Mar 12 '19 at 08:54
  • Is the minusList is the array that you are using to populate the items of the adapter if so, remove the item from the minusList and then call notifyItemRemoved at position if not remove the item from the array that you are using in the adapter then call notifyItemRemoved and do this outside your onbind, if you give more info of your code, people may help you better so please give more info :) – Antoine El Murr Mar 12 '19 at 10:03

6 Answers6

7

1.Why does it happen?

holder.itemView.setVisibility(View.GONE); This will not work in RecyclerView.

itemView is a child view in RecyclerView. Unlike the other ViewGroup (FrameLayout,etc), RecyclerView ignores childen's visibility during layout process.

2.How to solve it?

Option1 Use a regular view group such as FrameLayout to wrap your real layout, and hide your real layout: findViewById(R.id.layout_to_hide).setVisibility(View.GONE)

<FrameLayout android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <LinearLayout android:id="@+id/layout_to_hide"
                  android:layout_width="match_parent"
                  android:layout_height="wrap_content">
         //Put here your views
    </LinearLayout>
</FrameLayout>

Option2 Change the itemView’s heigh to 0 so we can't see it

holder.itemView.setLayoutParams(new RecyclerView.LayoutParams(0, 0));

Option3 If this item shouldn't be in List, then simply don't let it in adapter data, or remove it.

3.Learn more

1. Why the other view group such as FrameLayout works fine with children's visibibilty?

They don't compute the child's layout params if it's GONE

enter image description here

enter image description here

enter image description here

2. Why RecyclerView doesn't?

RecyclerView still compute the child's layout params if it's GONE so it still occupies spaces.

recycler view

Bruce Lin
  • 311
  • 3
  • 6
4

instead of using holder.itemView.setVisibility(View.GONE);, use this:

  ViewGroup.LayoutParams params = holder.itemView.getLayoutParams();
  params.height = 0;
  holder.itemView.setLayoutParams(params);
Hadi Ahmadi
  • 1,924
  • 2
  • 17
  • 38
  • This should be the accepted solution, at least it worked for me – Kaiser Mar 13 '20 at 15:52
  • 1
    The problem with this approach is that if you have an `ItemDecoration` between the items, you'll still have the separator before and after the removed items. – Thomas Jun 14 '21 at 18:36
0

Please try this one

    for(int j =0; j < minusList.size(); j++){

      int availableRooms =  minusList.get(j);

      if(norooms > availableRooms){        //norooms is the number of rooms wanted
        holder.itemView.setVisibility(View.GONE);
        mAdapter.notifyItemRemoved(position); 
     }else{
         holder.itemView.setVisibility(View.VISIBLE);
         holder.rRoomsLeft.setText("Room available");
     }
}
Abhinav Gupta
  • 2,225
  • 1
  • 14
  • 30
Shanto George
  • 994
  • 13
  • 26
0

I guess you say "occupy space" because row is there but not displaying "Room Available".

Remove one row from RecyclerView is done by remove it from the underline list first and call either notifyItemRemoved or notifyDatasetChanged, not by hiding the rows's view.

In your case you need to remove items from minusList first and then call notifyItemRemoved, else if getItemCount() still returns minusList.size, RecyclerView still thinks row is there, even it is not visible.

AIMIN PAN
  • 1,563
  • 1
  • 9
  • 13
  • I'm retrieving the data from firebase nothing to do with the `minusList` it's a different data – nani10 Mar 12 '19 at 07:40
0
ViewGroup.LayoutParams params = chatsViewHolder.itemView.getLayoutParams();
params.height = 0;
chatsViewHolder.itemView.setLayoutParams(params);
Elletlar
  • 3,136
  • 7
  • 32
  • 38
Tanjim ahmed
  • 473
  • 4
  • 15
0

In some cases changing only visibility attribute might still end up as allocated blank space (because of parent view's padding, margins, inner elements etc). Then changing height of the parent view helps:

holder.itemView.setVisibility(View.GONE); 
holder.itemView.setLayoutParams(new RecyclerView.LayoutParams(0, 0));

Then be sure that in the condition that it should be visible, also set:

holder.itemView.setVisibility(View.VISIBLE);
holder.itemView.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));

You need to do that because the viewHolder is recycled as you scroll, if you change properties as this and never return them to their natural state, other elements will be already hidden in the event they reuse the same view.

Koustuv Ganguly
  • 897
  • 7
  • 21