How to hide an item from Recycler View on a particular condition?

102.7k views Asked by At

I am using Firebase Recycler Adapter (Firebase UI Library) to populate Recycler View. I want to hide an item(row) on a condition. I have a LinearLayout containing a recycler view.

I set linear layout visibility to Gone in populateViewHolder() method of recycler view adapter.

@Override
protected void populateViewHolder(UsersViewHolder viewHolder, User user, int position) {

    if (user.getUserEmail().equals(Utils.decodeEmail(userEmail))) {
        viewHolder.llMain.setVisibility(View.GONE);
        return;
    }

    viewHolder.tvUserEmail.setText(user.getUserEmail());
}

It hides the LinearLayout but the row remains there with empty space.

Is there any method I should override to overcome this or is there any way to achieve the result?

12

There are 12 answers

8
Cătălin Florescu On BEST ANSWER

You should hide all views or parent from UsersViewholder layout xml. You should hide entire viewholder or each view

Entire viewholder:

itemView.setVisibility(View.GONE);

or each element:

view.setVisibility(View.GONE);

But don't forget to set them VISIBLE otherwise, you will end up with some strange things from recycling

2
Fartab On

There is no built in way to hide a child in RecyclerView. But you can implement this feature in your Adapter.

public class MyAdapter extends RecyclerView.Adapter<...>{
    List<Object> items;
    Map<Integer,Object> deletedItems;
    ...

    public void hideItem(final int position) {
         deletedItems.add(position, items.get(position));
         items.remove(position);
         notifyItemRemoved(position);
    }

    ....
}
1
JustBasitAli On

To eliminate empty spaces between items in the list, incorporate the following code within the onBindViewHolder method of your adapter class:

holder.itemView.setLayoutParams(new RecyclerView.LayoutParams(0, 0))
4
Samin On

IF

view.setVisibility(View.GONE);

gives you a Blank view

Then follow This.

public static class Data_ViewHolder extends RecyclerView.ViewHolder {
    private final LinearLayout layout;
    final LinearLayout.LayoutParams params;

    public Show_Chat_ViewHolder(final View itemView) {
        super(itemView);
        .
        .
        .
        layout =(LinearLayout)itemView.findViewById(R.id.show_item_layout);
        params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 
        ViewGroup.LayoutParams.WRAP_CONTENT);
        .
        .
        .
    }

    private void Layout_hide() {
        params.height = 0;
        //itemView.setLayoutParams(params); //This One.
        layout.setLayoutParams(params);   //Or This one.

    }
  }

Now Call from Adapter

mFirebaseAdapter = new FirebaseRecyclerAdapte......{
public void populateViewHolder.....{

if(model.getData().equals("..Something.."))
  {
      viewHolder.Layout_hide();
  }
else
      viewHolder.Person_Email(model.getEmail());
   }
 }
8
incognito On

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.

0
Nexen On

It seems like RV internally caches root view info so changing it's visibility does nothing to occuppied space by the item.

Wrap you RV item view with FrameLayout and set View.GONE to inner view. This way occupped space will be cleared correctly as well as item won't be shown at all.

1
hotMule On

I do not recommend answers with setting height and width of View to 0 because adapter still needs to render them and if there are too many hidden items this can cause lags, it is better to change the list itself and then send it to the adapter

0
Jinal Patel On
private fun hideShowItemView(itemView: View, toShow: Boolean) {
        itemView.isVisible = toShow
        itemView.layoutParams.height = if (toShow) ViewGroup.LayoutParams.WRAP_CONTENT else 0
 }
  1. itemView is an ItemView of the ViewHolder
  2. toShow is a boolean to hide or show item of recyclerview

Use below line of code in onBindViewHolder block as per the requirement,

To hide Item : hideShowItemView(holder.itemView, false)

To show Item : hideShowItemView(holder.itemView, true)
0
Rajeswar Mohanty On

this code is not working now:

holder.itemView.setVisibility(View.VISIBLE);

I am using this:

holder.itemView.findViewById(R.id.card).setVisibility(View.GONE);

you can easily send the ViewHolder value to your action function.

1
Sreejesh K Nair On

"GONE" will not remove the space occupied by the item ....you can use

if (condition) {
         item.layoutParams.height = 0
         item.layoutParams.width = 0
}

inside "onBindViewHolder"

0
Goodlife On
public class OfferViewHolder extends RecyclerView.ViewHolder {
    public TextView textViewOfferName;
    public LabelImageView labelImageView;
    public TextView textViewOldPrice;
    public TextView textViewNewPrice;
    public TextView textViewShopName;
    public TextView textViewTimeDate;
    public TextView textViewDistance;

    public LinearLayout linearLayoutMain;


    public OfferViewHolder(View view) {
        super(view);
        linearLayoutMain=(LinearLayout) view.findViewById(R.id.ll_main);
        textViewOfferName = (TextView) view.findViewById(R.id.textViewoffername);
        labelImageView=(LabelImageView) view.findViewById(R.id.labelImageView) ;
        textViewOldPrice=(TextView) view.findViewById(R.id.textViewOldPrice);
        textViewNewPrice=(TextView) view.findViewById(R.id.textViewNewPrice);
        textViewShopName=(TextView) view.findViewById(R.id.textViewShopName);
        textViewTimeDate=(TextView) view.findViewById(R.id.textViewDate);
        textViewDistance=(TextView) view.findViewById(R.id.textViewDistance);

        linearLayoutMain.setVisibility(View.GONE);
        textViewOfferName.setVisibility(View.GONE);
        labelImageView.setVisibility(View.GONE);
        textViewOldPrice.setVisibility(View.GONE);
        textViewNewPrice.setVisibility(View.GONE);
        textViewShopName.setVisibility(View.GONE);
        textViewTimeDate.setVisibility(View.GONE);
        textViewDistance.setVisibility(View.GONE);



    }


}`enter code here`

THEN IN YOUR ADAPTER

 if (a.equals(offer.getOfferCategory())) {


                        if (offer.getOfferCategory()==null){
//                            chatMessageViewHolder.getLinearLayoutMain().setVisibility(View.GONE);
//                            chatMessageViewHolder.linearLayoutMain.setLayoutParams(new RecyclerView.LayoutParams(0, 0));


                        }
                        else {
                            chatMessageViewHolder.itemView.setVisibility(View.VISIBLE);
                            chatMessageViewHolder.textViewShopName.setText(offer.getOfferCategory());
                            chatMessageViewHolder.linearLayoutMain.setVisibility(View.VISIBLE);
                            chatMessageViewHolder.textViewOfferName.setVisibility(View.VISIBLE);
                            chatMessageViewHolder.labelImageView.setVisibility(View.VISIBLE);
                            chatMessageViewHolder.textViewOldPrice.setVisibility(View.VISIBLE);
                            chatMessageViewHolder.textViewNewPrice.setVisibility(View.VISIBLE);
                            chatMessageViewHolder.textViewShopName.setVisibility(View.VISIBLE);
                            chatMessageViewHolder.textViewTimeDate.setVisibility(View.VISIBLE);
                            chatMessageViewHolder.textViewDistance.setVisibility(View.VISIBLE);

                        }

Thank you lorescu George Cătălin and Dhalav

0
Suvajit Patra On

If you are hiding whole itemView and facing the problem of blank spaces.

Try this to hide the itemView.

holder.itemView.setVisibility(View.GONE);
ViewGroup.LayoutParams params = holder.itemView.getLayoutParams();
params.height = 0;
params.width = 0;
holder.itemView.setLayoutParams(params);

And this to show it.

holder.itemView.setVisibility(View.VISIBLE);

This is a recyclerView, so use both in if else block or you might encounter some unintended UI issues.