Android中的RecyclerView在ConstraintLayout布局中无法滚动。

38

我有一个在约束布局中的RecyclerView,但是我无法使其滚动,列表会在屏幕下方继续而没有滚动条。如果我将布局更改为相对布局,则滚动正常工作。

如何使它滚动?

以下XML显示了我的布局,RecyclerView位于底部。布局顶部有图像和描述。此屏幕设置占据屏幕的30%。接着是分隔符和应该占据其余屏幕且无法滚动的RecyclerView。

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/gradient_top">

   <android.support.v7.widget.AppCompatImageView
        android:id="@+id/imageViewLock"
        android:layout_width="80dp"
        android:layout_height="80dp"
        android:layout_marginBottom="10dp"
        android:layout_marginTop="16dp"
        app:layout_constraintBottom_toTopOf="@+id/textViewPermissionsTitle"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/ic_phone_lock"/>

    <TextView
        android:id="@+id/textViewPermissionsTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="8dp"
        android:gravity="center"
        android:paddingLeft="24dp"
        android:paddingRight="24dp"
        android:text="@string/allow_permissions"
        android:textColor="@color/white"
        android:textSize="@dimen/description_text_size"
        app:layout_constraintBottom_toTopOf="@+id/guideline1"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"/>

    <android.support.constraint.Guideline
        android:id="@+id/guideline1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.3"/>


    <View
        android:id="@+id/viewSeparator"
        android:layout_width="match_parent"
        android:layout_height="0.7dp"
        android:layout_marginTop="10dp"
        android:background="@color/bright_blue"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="@+id/guideline1"/>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerViewPermissions"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:scrollbarSize="1dp"
        android:scrollbarThumbVertical="@color/white"
        android:scrollbars="vertical"
        app:layout_constraintTop_toBottomOf="@+id/viewSeparator" />


</android.support.constraint.ConstraintLayout>
5个回答

80

要使一个 RecyclerView 可以滚动,必须满足以下两个条件之一:

  • RecyclerView 的高度小于其所有项的高度
  • RecyclerView 位于可以滚动的父级布局内部

ConstraintLayout 不是可以滚动的父级布局,所以我们需要确保 RecyclerView 的高度“太小”,这将使用户可以滚动其子项。

最简单的方法就是为 RecyclerView 指定一个定义好的高度,可以像这样:

android:layout_height="200dp"

当然,这仅适用于您预先知道您想要的RecyclerView的确切大小,而这通常并不是情况。

更好的解决方案是使用约束来定义您的RecyclerView的高度。第一步是将其高度设置为0dp,可以认为是“匹配约束”。换句话说,您告诉系统根据其上下约束使RecyclerView尽可能高。

接下来,您必须定义上下约束。最简单的方法是将RecyclerView的顶部约束到其父项的顶部,将其底部约束到其父项的底部。例如:

android:layout_height="0dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"

或者,您可以将 RecyclerView 相对于其他一些视图进行定位。这可能看起来像这样:

android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="@+id/viewAboveMe"
app:layout_constraintBottom_toTopOf="@+id/viewBelowMe"
只要将高度设置为0dp并同时添加顶部和底部约束(前提是你的RecyclerView实际大小小于其内容),这将使你的RecyclerView可以按照预期进行滚动。

1
如果您使用“wrap_content”,则Recycler将使自己尽可能高以包装所有内容...但父级将被截断。如果您使用0dp加下部约束,则会使Recyclerview比其内容更小...现在Recyclerview的滚动属性就会启动。 - Ben P.
为了支持滚动,您的RecyclerView必须具有一些固定高度(小于其内容)。特别是在ConstraintLayout中,您可以提供0dp的高度,然后提供app:layout_constraintTop_xxx="@id/some_other_view"app:layout_constraintBottom_xxx="@id/some_other_view"(其中“xxx”可以替换为toBottomOftoTopOf等)。这将“约束”RecyclerView并定义其大小。我只提到了底部约束,因为问题已经提供了顶部约束。 - Ben P.
我花了数小时尝试各种方法来正确地使用RecycleView。每当其中的项目超过分配的空间时,它就会溢出。 match_parentwrap_content都像RecycleView是唯一存在的元素一样运作,因此项目将从屏幕顶部绘制到底部覆盖其他元素。非常感谢! - FRob
3
在某些情况下,我不知道为什么将recyclerView的高度设置为0dp并设置所有垂直约束条件无效。我成功地通过使用LinearLayout替换ConstraintLayout,并在父容器和recyclerview本身上都将高度设置为match_parent来使其水平滚动。 - reavcn
1
对我来说,将width="0dp"应用于recycler非常有帮助。必要的上下约束已经设置好了,高度设置为0dp,但是没有起作用。从同事那里听说,在ConstraintLayout中不推荐使用match_parent,并且将宽度也更改了,这样就解决了问题 :) - Eduards Pozarickis
显示剩余4条评论

9
有时会因为没有限制RecyclerView的底部而出现这种情况,导致RecyclerView的高度无限延伸超出屏幕可视范围。

是的,它很有用。它解决了我的问题。谢谢你。 - Revansiddappa

2
在RecyclerView中,以下更改对我有用。
<androidx.recyclerview.widget.RecyclerView.   
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@id/idBelowView"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHeight_default="wrap"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/idAboveView" />

2
这对我很有用:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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="match_parent"
    tools:context=".MainActivity">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/constraintLayout2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        ..... other controls ....

    </androidx.constraintlayout.widget.ConstraintLayout>

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginStart="1dp"
        android:layout_marginEnd="1dp"
        android:layout_marginBottom="1dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/constraintLayout2" />
</androidx.constraintlayout.widget.ConstraintLayout>

1

我通过以下的XML结构模式解决了相同的问题 -

                 <androidx.constraintlayout.widget.ConstraintLayout
                        android:layout_width="match_parent"
                       /*be carefull about the height.It need to be match parent.*/
                        android:layout_height="match_parent">
        
                      Others views are here .....
        
                        <androidx.recyclerview.widget.RecyclerView
                            android:layout_width="match_parent"
                            android:layout_height="0dp" /*Must be 0dp in height*/
                            app:layout_constraintBottom_toBottomOf="parent" 
                            /*Must have a layout_constraintBottom_toBottomOf */
                            *emphasized text*/>
        
                    </androidx.constraintlayout.widget.ConstraintLayout>

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