Home > Software design >  Constrain max size of RecyclerView
Constrain max size of RecyclerView

Time:04-14

I'm putting together a screen with 3 controls stacked vertically. Specifically, a RecyclerView sandwiched between two TextView. I have two situations I am trying to address.

  1. When few items are displayed in the RecyclerView the 3 items should be packed towards the top of the screen with blank space BELOW them.
  2. When many items are displayed in the RecyclerView the full screen will be used with the last TextView along the bottom of the screen and scrolling in the center RecyclerView.

I'm struggling to get the position of the last TextView correct as it either gets pushed off the screen or buried behind the RecyclerView if there are many items in the RecyclerView. What I need is a way to tell the RecyclerView to wrap contents, but stop growing when it starts to push the TextView off of the screen.

Below is my layout, any suggestions?

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

    <TextView
        android:id="@ id/topItem"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toTopOf="@ id/middleItem"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_chainStyle="packed" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@ id/middleItem"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:scrollbars="none"
        app:layout_constraintBottom_toTopOf="@ id/bottomItem"
        app:layout_constraintTop_toBottomOf="@ id/topItem" />

    <TextView
        android:id="@ id/bottomItem"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal|top"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toBottomOf="@ id/middleItem" />

</androidx.constraintlayout.widget.ConstraintLayout>

CodePudding user response:

Try the following:

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

    <TextView
        android:id="@ id/topItem"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="This is the top item."
        app:layout_constraintBottom_toTopOf="@ id/middleItem"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.0"
        app:layout_constraintVertical_chainStyle="packed" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@ id/middleItem"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:scrollbars="none"
        app:layout_constrainedHeight="true"
        app:layout_constraintBottom_toTopOf="@ id/bottomItem"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@ id/topItem"
        tools:itemCount="3" />

    <TextView
        android:id="@ id/bottomItem"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal|top"
        android:text="This is the bottom item."
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@ id/middleItem" />

</androidx.constraintlayout.widget.ConstraintLayout>

With three items in the RecyclerView:

enter image description here

With 50 items in the RecyclerView:

enter image description here

The key changes are:

  1. Added app:layout_constraintVertical_bias="0.0" to the top TextView to position the chain always at the top;
  2. Added app:layout_constrainedHeight="true" to the RecyclerView to make sure views don't go off-screen;
  3. Changed match_parent to 0dp and set the horizontal constraints for direct children of the ConstraintLayout.
  4. Changed the RecyclerView's height to '0dp'.

Update: Although the above works, it is a little overdone. As noted in the comments, the same effect can be accomplished by simply setting the height of the RecyclerView to 0dp.

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

    <TextView
        android:id="@ id/topItem"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="This is the top item."
        app:layout_constraintBottom_toTopOf="@ id/middleItem"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_chainStyle="packed" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@ id/middleItem"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:scrollbars="none"
        app:layout_constraintBottom_toTopOf="@ id/bottomItem"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@ id/topItem"
        tools:itemCount="3" />

    <TextView
        android:id="@ id/bottomItem"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal|top"
        android:text="This is the bottom item."
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@ id/middleItem" />

</androidx.constraintlayout.widget.ConstraintLayout>
  • Related