ConstraintLayout 中 ScrollView 内的非滚动 WRAP_CONTENT RecyclerView

Cha*_*ltz 5 android android-layout android-recyclerview

我想记录我遇到的问题和解决方案以造福他人,并寻求解决方案中关键缺陷的帮助。

我想要RecyclerView在布局中具有任意数量的行,并且具有许多其他视图。在RecyclerView和其他ViewS的关系是在ScrollView那个卷轴,但RecyclerView本身不应该滚动。

由于 中的行数RecyclerView未知,而且我需要在 紧下方有其他视图RecyclerView,因此我不能使用固定高度或match_parent.

我遇到了一些奇怪的问题:当我更新RecyclerView数据(使用AsyncListDiffer)并且 UI 应该更新时,整个RecyclerView会跳到它被约束在下面的视图之上,直接到父级的顶部。这不是 aConstraintLayout应该表现的方式。

然后我能够阻止这种情况发生,但是Views 下方的 sRecyclerView将消失 - 一旦RecyclerView数据更新就会出现。

解决方案:

  1. RecyclerViewand other Views 放在 a ConstraintLayoutinside a ScrollView(or NestedScrollView)
  2. RecyclerView高度设置为wrap_content(并且添加app:layout_constrainedHeight="true"不会造成伤害)
  3. 确保 RecyclerView 中的行具有固定的高度并且没有高度wrap_content

在将我的头撞在墙上并尝试了一些无效的建议解决方案后,这对我很有帮助:在约束布局中使 RecyclerView 的高度为“wrap_content”

这个解决方案非常简单。布局可以是这样的:

    <ScrollView
        android:id="@+id/scrollView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <!-- other Views -->

            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/recyclerView"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/otherView"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintBottom_toTopOf="@+id/anotherView"
                />

                <!-- other Views -->
        </androidx.constraintlayout.widget.ConstraintLayout>

    </ScrollView>
Run Code Online (Sandbox Code Playgroud)

然后是一行的布局:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
                                                   xmlns:tools="http://schemas.android.com/tools"
                                                   xmlns:app="http://schemas.android.com/apk/res-auto"
                                                   android:id="@+id/constraintLayout"
                                                   android:layout_width="match_parent"
                                                   android:layout_height="?attr/listPreferredItemHeight">

<!-- other views -->

</androidx.constraintlayout.widget.ConstraintLayout>
Run Code Online (Sandbox Code Playgroud)

Here's the problem: I'm not a fan of fixed-height rows. What if other content needs to go in there? What if the user changes their text size? I much prefer flexible layouts that can adapt in size. But if I do that, then the RecyclerView takes up a screen's worth of height inside the ScrollView, shoving all lower views off the bottom of the screen, no matter how few rows it contains.

The alternatives I can think of are to make all the other Views outside the RecyclerView become rows of the RecyclerView, or to avoid a RecyclerView altogether and programmatically add Views to a LinearLayout. These are much uglier approaches.

Is there a way to fix it so the rows of the RecyclerView can have a height of wrap_content?