Search code examples
androidandroid-layoutandroid-recyclerviewandroid-constraintlayoutandroid-progressbar

How to keep progressbar always below a recyclerView and not to be squeezed out of screen if there are too many items?


I am making a layout for showing scanned bluetooth device. Here is the layout:

<?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=".fragments.ScannedListFragment">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_view_scan_list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toTopOf="@id/progressBar_scan_list"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        tools:itemCount="12"
        tools:listitem="@layout/list_item_scanned_list" />

    <ProgressBar
        android:id="@+id/progressBar_scan_list"
        style="?android:attr/progressBarStyle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@id/recycler_view_scan_list"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

But when there are too many list items, the progressbar will be squeezed out of the screen. Just like this: demonstration1

I want to keep the progressbar stick to the bottom of the recyclerView when the screen has enough space to show all content and the progressbar can be completely shown above the bottom of the screen without scrolling even if there are too many items in the recyclerView.

I tried vertically chaining two views and packed chain with bias but no luck. Also, I found that adding app:layout_constraintHeight_max="" for the recyclerView can achieve similar effect. But it seems not a general solution for different screen sizes.


Solution

  • Create a vertical chain by constraining the bottom of the ProgressBar to the parent, then set the chain style to packed so that both views stick together and then set the vertical bias to 0 to align them to the top of the parent. To prevent the RecyclerView from pushing the ProgressBar out of the screen set the app:layout_constrainedHeight="true" attribute for the RecyclerView - it enforces constraints when the height is set to wrap_content.

    <?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=".fragments.ScannedListFragment">
    
        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recycler_view_scan_list"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            app:layout_constraintVertical_chainStyle="packed"
            app:layout_constraintVertical_bias="0"
            app:layout_constrainedHeight="true"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintBottom_toTopOf="@id/progressBar_scan_list"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            tools:itemCount="12"
            tools:listitem="@layout/list_item_scanned_list" />
    
        <ProgressBar
            android:id="@+id/progressBar_scan_list"
            style="?android:attr/progressBarStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintTop_toBottomOf="@id/recycler_view_scan_list"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>