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:

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 2:

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

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.