RecyclerView中的visibility gone是否仍占用空间?

7

这是我的当前代码。我想要在我的recyclerview上隐藏一个特定的项目,但是当我使用visibility.gone时,它仍然占据了recyclerview中的空间。我也尝试了所有可能的解决方案如何在Recycler View上隐藏一个项目,在特定的条件下? 请帮忙。

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

}

这是我的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" />

@DhavalSolanki 修改了我的帖子。 - nani10
实际上,我要求单元 XML,也就是用于显示单行的布局。 - Dhaval Solanki
如果你正在调用 notifyItemRemoved,那么 holder.itemView.setVisibility(View.GONE); 的作用是什么?如果该项被移除,则其可见性无关紧要。另外,我不知道你在哪里调用这段代码,请提供一个 [mcve]。 - ADM
如果我放整个代码的话,那就太多了,除非你想要每一个细节哈哈。 - nani10
那是最简单和最小的笑话。 - nani10
显示剩余6条评论
6个回答

8

1. 为什么会发生这种情况?

holder.itemView.setVisibility(View.GONE); 这在 RecyclerView 中不起作用。

itemView 是 RecyclerView 中的子视图。与其他 ViewGroup(如 FrameLayout 等)不同,RecyclerView 在布局过程中忽略子视图的可见性。

2. 如何解决这个问题?

选项1: 使用常规的视图组,例如 FrameLayout,将您的真实布局包装起来,并隐藏您的真实布局: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>

选项2:将itemView的高度更改为0,这样我们就看不到它了。

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

选项3:如果这个项目不应该在列表中出现,那么就不要在适配器数据中添加它或者将其移除。

3.了解更多

1. 为什么其他的视图组(如FrameLayout)与子视图的可见性一起使用没有问题?

如果GONE,它们不会计算子视图的布局参数。

enter image description here

enter image description here

enter image description here

2. 为什么RecyclerView不行?

RecyclerView仍然会计算子视图的布局参数,即使是GONE状态,因此它仍然会占用空间。

recycler view


4

不要使用holder.itemView.setVisibility(View.GONE);,而是使用以下代码:

  ViewGroup.LayoutParams params = holder.itemView.getLayoutParams();
  params.height = 0;
  holder.itemView.setLayoutParams(params);

这应该是被接受的解决方案,至少对我有效。 - Kaiser
1
这种方法的问题在于,如果在项目之间有一个“ItemDecoration”,则在删除项目之前和之后仍将保留分隔符。 - Thomas

0
在某些情况下,仅更改可见性属性可能仍会导致分配的空白空间(因为父视图的填充、边距、内部元素等)。然后更改父视图的高度可以解决这个问题:
holder.itemView.setVisibility(View.GONE); 
holder.itemView.setLayoutParams(new RecyclerView.LayoutParams(0, 0));

然后请确保在应该可见的情况下,也进行设置:

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

你需要这样做,因为viewHolder在滚动时被回收利用,如果你改变了属性并且没有将它们返回到自然状态,其他元素将已经隐藏,以防止它们重用相同的视图。


0

我猜你说“占用空间”,是因为行存在,但没有显示“房间可用”。

从RecyclerView中删除一行是通过先从底层列表中删除它,然后调用notifyItemRemoved或notifyDatasetChanged来完成的,而不是隐藏行的视图。

在你的情况下,你需要先从minusList中删除项目,然后调用notifyItemRemoved,否则如果getItemCount()仍然返回minusList.size,RecyclerView仍然认为该行存在,即使它不可见。


我正在从Firebase检索数据,与“minusList”无关,这是不同的数据。 - nani10

0
ViewGroup.LayoutParams params = chatsViewHolder.itemView.getLayoutParams();
params.height = 0;
chatsViewHolder.itemView.setLayoutParams(params);

0
请尝试这个。
    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");
     }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接