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

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?



Solution 1:[1]

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

Solution 2:[2]

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.

Solution 3:[3]

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

Solution 4:[4]

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.

Solution 5:[5]

"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"

Solution 6:[6]

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

    ....
}

Solution 7:[7]

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

Solution 8:[8]

holder.itemView.setVisibility(View.VISIBLE); is not working now. I am using this

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

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

Solution 9:[9]

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

Solution 10:[10]

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.

Solution 11:[11]

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)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 htafoya
Solution 3 Community
Solution 4
Solution 5 Sreejesh K Nair
Solution 6 Fartab
Solution 7 Goodlife
Solution 8 user2982173
Solution 9 hotMule
Solution 10 Nexen
Solution 11