Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hiding views in RecyclerView

Tags:

android

I have code like this

public static class MyViewHolder extends RecyclerView.ViewHolder {
    @InjectView(R.id.text)
    TextView label;

    public MyViewHolder(View itemView) {
        super(itemView);
        ButterKnife.inject(this, itemView);
    }

    public void hide(boolean hide) {
        label.setVisibility(hide ? View.GONE : View.VISIBLE);
    }
}

which maps to a single row in a RecyclerView. R.id.text is in fact the root view of the layout that gets inflated and passed in to the constructor here.

I'm using the default implementation of LinearLayoutManager.

In bindViewHolder, I call hide(true) on an instance of MyViewHolder, but instead of collapsing the row as expected, the row becomes invisible, maintaining its height and position in the RecyclerView. Has anyone else run into this issue?

How do you hide items in a RecyclerView?

like image 269
Tony J Huang Avatar asked Dec 19 '14 22:12

Tony J Huang


3 Answers

There is no built in way to hide a child in RV but of course if its height becomes 0, it won't be visible :). I assume your root layout does have some min height (or exact height) that makes it still take space even though it is GONE.

Also, if you want to remove a view, remove it from the adapter, don't hide it. Is there a reason why you want to hide instead of remove ?

like image 176
yigit Avatar answered Nov 01 '22 08:11

yigit


Put method setVisibility(boolean isVisible) in ViewHolder.

You can change itemView params(width and height) for LayoutManager:

public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
    ...

    public void setVisibility(boolean isVisible){
        RecyclerView.LayoutParams param = (RecyclerView.LayoutParams)itemView.getLayoutParams();
        if (isVisible){
            param.height = LinearLayout.LayoutParams.WRAP_CONTENT;
            param.width = LinearLayout.LayoutParams.MATCH_PARENT;
            itemView.setVisibility(View.VISIBLE);
        }else{
            itemView.setVisibility(View.GONE);
            param.height = 0;
            param.width = 0;
        }
        itemView.setLayoutParams(param);
    }

    public ViewHolder(View itemView) {
        super(itemView);
        ...
    }
}

and change visibility for ItemDecoration (Divider):

public class DividerItemDecoration extends RecyclerView.ItemDecoration {
    ...

    @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        ...

        for (int i = 0; i < parent.getChildCount(); i++) {

            if (parent.getChildAt(i).getVisibility() == View.GONE) 
                continue;

            /* draw dividers */    

        }
    }
}
like image 42
Dmitry Velychko Avatar answered Nov 01 '22 08:11

Dmitry Velychko


You CAN do it!

First, you need to detect which position of item that you want to hide. You can custom getItemViewType to do it.

Next, on onCreateViewHolder, depend on the view type. You can do something like this:

if(viewType == TYPE_HIDE) {
                v = LayoutInflater.from(parent.getContext()).inflate(R.layout.empty_item, parent, false);
                vHolder = new ViewHolder(context, v, viewType, this);
                break;
        }
        return vHolder; 

-> empty item is a layout that have nothing, (in other word, it is default layout whenever created). or code:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

</LinearLayout>

Hope it help!

like image 12
Lạng Hoàng Avatar answered Nov 01 '22 06:11

Lạng Hoàng