Android 在RecyclerView中隐藏视图

Android 在RecyclerView中隐藏视图,android,Android,我有这样的代码 public static class MyViewHolder extends RecyclerView.ViewHolder { @InjectView(R.id.text) TextView label; public MyViewHolder(View itemView) { super(itemView); ButterKnife.inject(this, itemView); } public

我有这样的代码

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);
    }
}
它映射到
RecyclerView
中的一行
R.id.text
实际上是布局的根视图,该视图在此处膨胀并传递给构造函数

我使用的是
LinearLayoutManager
的默认实现

bindViewHolder
中,我对
MyViewHolder
的一个实例调用了
hide(true)
,但该行并没有按预期折叠,而是变为不可见,保持其在
RecyclerView
中的高度和位置。还有其他人遇到过这个问题吗


如何在RecyclerView中隐藏项目

没有内置的方法可以在RV中隐藏子对象,但当然,如果其高度变为0,它将不可见:)。我假设您的根布局确实有一些最小高度(或精确高度),这使得它即使不存在也仍然占用空间


此外,如果要删除视图,请将其从适配器中删除,不要隐藏它。你想隐藏而不是删除有什么原因吗?

好的,所以我最终的做法是我有了整个数据集,比如说,
myObjects
,我有一些场景,我只想显示该数据集的子集

由于在
RecyclerView
中设置行的可见性不会导致高度崩溃,并且设置行的高度似乎也没有任何作用,我要做的就是保留一个名为
myObjectsShown
的二级数据集,它只不过是一个
列表
,它将索引到
myObjects
,以确定将显示哪些对象

然后,我会间歇性地更新
myObjectsShown
,以包含正确的索引

所以,

public int getItemCount() {
    return myObjectsShown.size();
}

你能行

首先,您需要检测要隐藏项目的哪个位置。您可以自定义getItemViewType来执行此操作

接下来,在onCreateViewHolder上,取决于视图类型。您可以这样做:

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; 
->空项是一个没有任何内容的布局(换句话说,无论何时创建,它都是默认布局)。或代码:

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


希望能有帮助

Put方法
setVisibility(布尔值可见)
ViewHolder

您可以更改
LayoutManager
itemView
参数(宽度和高度):

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);
        ...
    }
}
if (item.isShown) {
    vh.FooterLayout.setVisibility(View.Visible);
} else {
    vh.FooterLayout.setVisibility(View.Gone);
}
并更改
项目装饰的可见性(分隔符):

public类DividerItemDecoration扩展了RecyclerView.ItemDecoration{
...
@凌驾
公共void onDraw(画布c、RecyclerView父级、RecyclerView.State){
...
对于(int i=0;i
为了完整起见,您应该注意,将视图可见性设置为GONE不会隐藏页边距。您需要这样做:

       if(itemView.getVisibility() != GONE) itemView.setVisibility(GONE);
       RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) itemView.getLayoutParams();
       layoutParams.setMargins(0, 0, 0, 0);
       itemView.setLayoutParams(layoutParams);

对于在RecyclerView中隐藏视图,我在
OnBindViewHolder
中隐藏/显示视图:

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);
        ...
    }
}
if (item.isShown) {
    vh.FooterLayout.setVisibility(View.Visible);
} else {
    vh.FooterLayout.setVisibility(View.Gone);
}
例如,从活动中,我只需重新绘制所需项目:
\u postListAdapter.notifyItemChanged(position)
//如果您想显示/隐藏页脚-位置是
amountOfPosts.size()
,还可以更改bool变量-
amountOfPosts[amountOfPosts.size()]。isShown

您是否尝试过
RecyclerView.getLayoutManager().removeViewAt())
永远不要在LM中直接调用这些方法。他们是由LM管理儿童Hello。看看我的答案。不,我实际上试着将某些行的高度设置为0。LayoutManager不考虑行高更改。不过,您是对的,解决方案是从适配器中“删除”有问题的对象。请参阅我的答案。LayoutManager确实尊重项目高度。我想知道你是如何改变它们的。我假设您正在调用view.setLayoutParams,它将触发LayoutManager中的重新布局,并将获得新的大小。这里应该还有别的问题哦,你是对的,我刚刚意识到我把高度设置错了。我会将您的答案标记为正确。请注意,如果您使用装饰器(例如,在项目之间添加分隔符),您的“不可见”项目仍将被装饰。@yigit我有一个理由,我将前两个项目作为常量项目。因此,它们始终是列表中的第一项和第二项。列表上的第一项是控制器,第二项是“添加卡”。当我按下控制器中的按钮时,“添加卡”出现。该项的其余部分是模型列表的标准表示形式。我试图模仿Facebook上的post功能,你总是在列表的顶部有一张“发表你的想法”卡片,所以我想我可以通过RecyclerView创建一个复合视图。但也许这只是一种错误的方式。这是非常聪明和简单的。这应该是最好的答案,因为您真的不必干涉
getItemViewType
或其他任何事情。但是它可以动态地隐藏你不想显示的孩子,而且还考虑了高度的变化。非常聪明的回答我认为将
布局高度设置为
0dp
包装内容是个好主意,如果将其设置为
match\u parent
,则每个空单元格都将占据父视图的大小…虽然这起作用,但会导致大量循环测量,并使滚动非常不方便。@但如果列表中有许多隐藏项,则应考虑其他显示它们的算法。例如,更改布局管理器。我们是否需要处理LayoutParams,而不仅仅是View。Goe是否需要执行此操作?