38

I have a recyclerView inside a constraint layout and I cannot make it scroll, the list just continues below the screen without scroll possibility. If I turn the layout into relative layout the scroll works fine.

how can I get it to scroll?

the the following XML shows my layout, the recycler view is in the bottom. the layout has an image and description at the top of the screen. this screen setup takes 30% of the screen. followed by and a separator and the recycler view that should take the rest of the screen and that cannot scroll

<?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>
Cœur
  • 37,241
  • 25
  • 195
  • 267
BennyP
  • 1,737
  • 1
  • 18
  • 24

5 Answers5

79

For a RecyclerView to scroll, one of two things must be true:

  • The RecyclerView has a smaller height than all of its items
  • The RecyclerView is inside a scrolling parent

ConstraintLayout is not a scrolling parent, so we have to make sure that the RecyclerView is "too small", which will cause it to let the user scroll its children.

The easiest way is to just give the RecyclerView a defined height, with something like this:

android:layout_height="200dp"

Of course, this only works if you know ahead of time exactly how big you want your RecyclerView to be, and this is not usually the case.

A better solution is to use constraints to define the height of your RecyclerView. The first step is to give it a height of 0dp, which can be thought of as "match constraints". In other words, you're telling the system to make the RecyclerView as tall as it needs to be in order to satisfy its top and bottom constrains.

Next, you must define top and bottom constraints. The simplest would be to constrain the RecyclerView's top to the parent's top and its bottom to the parent's bottom. That might look like this:

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

Or, you could position the RecyclerView relative to some other views. That might look like this:

android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="@+id/viewAboveMe"
app:layout_constraintBottom_toTopOf="@+id/viewBelowMe"

As long as you combine a height of 0dp with both top and bottom constraints (and as long as your RecyclerView is actually smaller than its contents), this will allow your RecyclerView to scroll as desired.

Original

Your RecyclerView is using wrap_content for its height. If you want it to scroll, you must provide a fixed height, or, inside a ConstraintLayout, use 0dp for its height and give it an app:layout_constraintBottom_xxx attribute.

Ben P.
  • 52,661
  • 6
  • 95
  • 123
  • it works! however I don't understand why, how does the 0dp help to scroll, and why doesn't it work with wrap_content – BennyP Jul 30 '17 at 07:11
  • 1
    If you use `wrap_content`, the recycler will make itself as tall as required to wrap everything... but the parent will cut the bottom of it off. If you use 0dp plus a constraint bottom, you're making the recyclerview _smaller_ than its contents... and now the scrolling properties of recyclerview kick in. – Ben P. Jul 30 '17 at 07:16
  • i did not got idea about **app:layout_constraintBottom_xxx** could you please explain – Nazim ch Sep 20 '17 at 08:27
  • @Nazimch In order to support scrolling, your `RecyclerView` must have some fixed height (that is smaller than its contents). Specifically inside a `ConstraintLayout`, you could provide a height of `0dp` and then provide `app:layout_constraintTop_xxx="@id/some_other_view"` and also `app:layout_constraintBottom_xxx="@id/some_other_view"` (where "xxx" could be replaced by `toBottomOf` or `toTopOf` etc). This will "constrain" the `RecyclerView` and define its size. I mentioned only the bottom constraint because the question already provided a top constraint. – Ben P. Sep 20 '17 at 17:28
  • I spent hours trying everything to get the `RecycleView` to work correctly. Whenever there were more items in it than would fit the alotted space it would just overflow. `match_parent` and `wrap_content` would both act like the `RecycleView` was the only element present, so items would be drawn from top to bottom of the screen over other elements. Thanks a bunch!!! – FRob Oct 06 '17 at 14:17
  • 3
    I don't know why, but in some cases setting the recyclerView height to 0dp and all its vertical constraints doesn't work. I managed to make it scroll horizontally by replacing ConstraintLayout with LinearLayout and setting heights to match_parent both on the parent and the recyclerview itself – reavcn Oct 03 '19 at 11:09
  • 1
    For me helped putting `width="0dp"` for the recycler. Necessary top&bottom constraints were put, the height was set to 0dp, but didn't help. From colleague heard that `match_parent` is not recommended in `ConstraintLayout` and changed the width as well and it worked :) – Eduards Pozarickis Oct 15 '19 at 08:22
  • @EduardsPozarickis I've used the same solution. It works fine. Seems 0dp is both the proper width and height for scrollable views inside constraint layout. – Samuel Urbanowicz Jun 02 '20 at 12:52
  • layout height 0dp helped me – Chandu Aug 04 '20 at 05:46
8

Sometimes it happens because of not constraining bottom of recycler view. Which causes recycler view to be of an infinite height that goes beyond the visible screen.

RHS.Dev
  • 412
  • 6
  • 18
2

This worked for me:

<?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>
live-love
  • 48,840
  • 22
  • 240
  • 204
2

In RecyclerView, below changes worked for me.

<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" />
Soorya
  • 179
  • 1
  • 5
1

I fixed the same problem by the following XML structure pattarn -

                 <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>
Gk Mohammad Emon
  • 6,084
  • 3
  • 42
  • 42