View.GONE会留下空白的空间。

8
我使用Firebase获取了两种类型的数据,并使用RadioButton对显示的数据进行排序。一切似乎都正常,但当其中一个数据类型被隐藏时仍然存在空白空间。请告诉我如何正确地隐藏/显示数据。
这是我得到的内容: 点击查看 适配器:
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int 
viewType) {
    switch (viewType) {
        case Person.PersonType.TYPE_1:
            View userType1 = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.driver_row, parent, false);
            return new PersonType1ViewHolder(userType1);
        case Person.PersonType.TYPE_2:
            View userType2 = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.fare_row, parent, false);
            return new PersonType2ViewHolder(userType2);
    }
    return super.onCreateViewHolder(parent, viewType);
}

@Override
protected void populateViewHolder(RecyclerView.ViewHolder viewHolder, 
Person model,
                                  int position) {
    if (viewHolder instanceof PersonType1ViewHolder) {
        ((PersonType1ViewHolder) viewHolder).time.setText("Full time: " + 
model.getTime());
        if (activate) {
            viewHolder.itemView.setVisibility(View.GONE);
        } else {
            viewHolder.itemView.setVisibility(View.VISIBLE);
        }
        return;
    }
    if (viewHolder instanceof PersonType2ViewHolder) {
        ((PersonType2ViewHolder) viewHolder).time.setText("Full time2: " + 
model.getTime());
        if (activate2) {
            viewHolder.itemView.setVisibility(View.GONE);
        } else {
            viewHolder.itemView.setVisibility(View.VISIBLE);
        }
private class PersonType1ViewHolder extends RecyclerView.ViewHolder {
    TextView time;
    PersonType1ViewHolder(View itemView) {
        super(itemView);
        time = itemView.findViewById(R.id.tv_time);
    }
}

private class PersonType2ViewHolder extends RecyclerView.ViewHolder {
    TextView time;
    PersonType2ViewHolder(View itemView) {
        super(itemView);
        time = itemView.findViewById(R.id.tv_time_two);
    }
}

行布局相同 - wrap_content

<androidx.cardview.widget.CardView 
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">

<RelativeLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <TextView
        android:id="@+id/tv_time"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView" />

</RelativeLayout>
</androidx.cardview.widget.CardView>

主活动 XML

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    tools:context=".MainActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rv_trip_list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@id/radio_button_group" />

    <Button
        android:id="@+id/add_trip"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentEnd="true"
        android:layout_alignParentBottom="true"
        android:onClick="addTrip"
        android:text="add" />

    <RadioGroup
        android:id="@+id/radio_button_group"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@id/add_trip"
        android:layout_centerHorizontal="true"
        android:orientation="horizontal">

        <RadioButton
            android:id="@+id/rb_all"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:checked="true"
            android:text="all" />

        <RadioButton
            android:id="@+id/rb_driver"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="driver" />

        <RadioButton
            android:id="@+id/rb_fare"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="fare" />
    </RadioGroup>

</RelativeLayout>

1
我们需要查看XML文件,Java代码看起来正确,错误一定在XML布局中。 - Marc
代码看起来没问题,可能是你的 XML 文件有问题。 - Krum
类似于普通的 XML - Maxim Filatov
你能发一下 itemView 被填充的代码吗?包括两个 ViewHolder 的实现。 - Cory Roy
5个回答

7

我不知道这是否正确,但我刚刚以编程方式设置了参数。

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

2

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

viewHolder.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


2

我也遇到了这样的问题,后来发现是适配器中 getItemCount() 方法的重写问题。我猜如果你指定了 getItemCount() 的数量,RecyclerView 即使隐藏它,也会为 ViewHolder 保留一个位置。以下是我解决问题的代码。

override fun getItemViewType(position: Int): Int {
    when {
        !importantImages.isNullOrEmpty() && !otherImages.isNullOrEmpty() -> {
            return when (position) {
                0 -> Important.ordinal
                else -> Other.ordinal
            }
        }
        otherImages.isNullOrEmpty() -> {
            return Important.ordinal
        }
        importantImages.isNullOrEmpty() -> {
            return Other.ordinal
        }
    }
    return 0
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
    return when (ViewType.values()[viewType]) {
        Important -> {
            val layoutInflater = LayoutInflater
                .from(parent.context)
                .inflate(R.layout.layout_important_list, parent, false)
            ImportantViewHolder(layoutInflater)
        }
        Other -> {
            val layoutInflater = LayoutInflater
                .from(parent.context)
                .inflate(R.layout.layout_other_list, parent, false)
            OtherViewHolder(layoutInflater)
        }
    }
}

override fun getItemCount(): Int = when {
    !importantImages.isNullOrEmpty() && !otherImages.isNullOrEmpty() -> {
        2
    }
    importantImages.isNullOrEmpty() && otherImages.isNullOrEmpty() -> {
        0
    }
    else -> {
        1
    }
}

希望这可以帮到你! :)

1

我也遇到了这个问题,我发现如果在外面添加一个容器并使用wrap_content,那么它就可以正常工作。

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/v_root"
        android:layout_width="match_parent"
        android:layout_height="48dp">
    </androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>

在 Java 代码中:

v_root.setVisibility(View.GONE);

v_root在编程中表示您的旧视图根。


0
问题不是很清楚。 但我可以向您保证,使用View.GONE后,视图变得不可见且不留空间。而使用View.INVISIBLE后,视图会留下一个不可见的空间。 如果它不能运行,那就意味着您的布局出了问题。

我也不明白为什么这不起作用,但它确实是这样。因此,我提出了一个问题。 - Maxim Filatov
尝试将行布局中的RelativeLayout更改为LinearLayout。 - Gius

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