I have a Fragment which is used to make searches. Its layout has a "search bar" at the top, and then there is a TextView and a RecyclerView where I display the results. I would like to hide/show the search bar and the TextView when user scrolls, like in this video, but instead of hiding the Toolbar my idea is to hide the search bar and the TextView. Something like this:

Expected result

I already have a custom Toolbar in the activity_main.xml that must be fixed across the activity, only the search bar and the TextView needs to be hidden/shown.

I tried to get it working using CoordinatorLayout, but all examples I found were to show/hide the Toolbar, hence I am not really sure if I can get what I want using CoordinatorLayout.

After multiple attempts with CoordinatorLayout, I decided to look for another solution and found this one. However, it does not work like in the sample. First of all, it breaks part of my code functionallity, and secondly altough the search bar and TextView are hidden/shown, the RecyclerView keeps it position instead of take the place of the other two views:

Search bar and TextViews are hidden but RecyclerView do not take their place

Finally, looking for more solutions I found this one that uses MotionLayout. It works great except for one problem. When the RecyclerView is empty, its visibility is GONE or the number of items to display can fit in the space available of the screen, the user can still scroll and hide the search bar and the TextView:

User can scroll even if there is nothing else to show

I don't expect this behaviour, I expect the views to collapse only when the RecyclerView is too big for the screen. How can achieve this?

I have been struggling with this the last couple of days and cannot find a solution, I hope you can help me. Find below the XML files. Thank you in advance!

Activity layout:

<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout 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:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:openDrawer="start">

    <!-- Contenedor principal para mostrar el Toolbar y el contenido oportuno-->
    <androidx.coordinatorlayout.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        
        <com.google.android.material.appbar.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <!-- Toolbar que hace de ActionBar -->
        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            android:elevation="4dp"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />

        </com.google.android.material.appbar.AppBarLayout>
        
        <FrameLayout
            android:id="@+id/fragment_container"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior"
            />

    </androidx.coordinatorlayout.widget.CoordinatorLayout>

    <!-- Menú para moverse por la app -->
    <com.google.android.material.navigation.NavigationView
        android:id="@+id/navigation_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:menu="@menu/menu" />

</androidx.drawerlayout.widget.DrawerLayout>

Fragment layout:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.motion.widget.MotionLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:motion="http://schemas.android.com/apk/res-auto"
    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"
    motion:layoutDescription="@xml/motionscene"
    tools:context=".SearchFragment">

    <LinearLayout
        android:id="@+id/buscador"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/cyan"
        android:orientation="vertical"
        android:paddingBottom="16dp"
        motion:layout_constraintEnd_toEndOf="parent"
        motion:layout_constraintStart_toStartOf="parent"
        motion:layout_constraintTop_toTopOf="parent"
        motion:layout_constraintBottom_toTopOf="@id/num_resultados">

        <SearchView
            android:id="@+id/search_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="16dp"
            android:background="@drawable/search_view_background"
            android:iconifiedByDefault="false"
            android:inputType="textPersonName"
            android:queryBackground="@android:color/transparent"
            android:queryHint="Buscar..." />

        <RadioGroup
            android:id="@+id/filtro_busqueda"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal"
            android:orientation="horizontal">

            <RadioButton
                android:id="@+id/nom_futbolistico_Rb"
                style="@style/SearchRadioButton"
                android:checked="true"
                android:text="@string/nombre_futbolistico" />

            <RadioButton
                android:id="@+id/nombre_Rb"
                style="@style/SearchRadioButton"
                android:layout_marginHorizontal="16dp"
                android:text="@string/nombre" />

            <RadioButton
                android:id="@+id/apellidos_Rb"
                style="@style/SearchRadioButton"
                android:text="@string/apellidos" />
        </RadioGroup>

    </LinearLayout>

    <TextView
        android:id="@+id/num_resultados"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/recycler_view_item_search"
        android:gravity="center_horizontal"
        android:paddingVertical="8dp"
        android:textAppearance="@style/TextAppearance.AppCompat.Medium"
        android:visibility="gone"
        motion:layout_constraintEnd_toEndOf="parent"
        motion:layout_constraintStart_toStartOf="parent"
        motion:layout_constraintTop_toBottomOf="@id/buscador" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/lista_deportistas_Rv"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        motion:layout_constraintEnd_toEndOf="parent"
        motion:layout_constraintStart_toStartOf="parent"
        motion:layout_constraintBottom_toBottomOf="parent"
        motion:layout_constraintTop_toBottomOf="@id/num_resultados"
        tools:listitem="@layout/listado_deportista_item" />

</androidx.constraintlayout.motion.widget.MotionLayout>

MotionScene:

<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:motion="http://schemas.android.com/apk/res-auto">

    <Transition
        motion:constraintSetEnd="@id/recogido"
        motion:constraintSetStart="@id/expandido">

        <OnSwipe
            motion:dragDirection="dragUp"
            motion:moveWhenScrollAtTop="false"
            motion:touchAnchorId="@id/lista_deportistas_Rv"
            motion:touchAnchorSide="top" />

    </Transition>

    <ConstraintSet android:id="@+id/expandido">
        <Constraint android:id="@id/buscador" >
            <PropertySet android:alpha="1" />
        </Constraint>
        <Constraint android:id="@id/num_resultados">
            <PropertySet android:alpha="1"
                motion:visibilityMode="ignore"/>
        </Constraint>
        <Constraint android:id="@id/lista_deportistas_Rv">
            <PropertySet motion:visibilityMode="ignore"/>
        </Constraint>
    </ConstraintSet>

    <ConstraintSet android:id="@+id/recogido">
        <Constraint
            android:id="@id/buscador"
            motion:layout_constraintEnd_toEndOf="parent"
            motion:layout_constraintStart_toStartOf="parent"
            motion:layout_constraintBottom_toTopOf="parent">
            <PropertySet android:alpha="0" />
        </Constraint>
        <Constraint
            android:id="@id/num_resultados"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            motion:visibilityMode="ignore"
            motion:layout_constraintEnd_toEndOf="parent"
            motion:layout_constraintStart_toStartOf="parent"
            motion:layout_constraintBottom_toTopOf="parent">
            <PropertySet android:alpha="0" />
        </Constraint>
        <Constraint android:id="@id/lista_deportistas_Rv">
            <PropertySet motion:visibilityMode="ignore"/>
        </Constraint>

    </ConstraintSet>

</MotionScene>
1

There are 1 best solutions below

0
On

This view hierarchy helped me achieve such behavior

    <LinearLayout>
            
                <CustomToolBarView /> (always visible view, something like Toolbar)
            
                <androidx.coordinatorlayout.widget.CoordinatorLayout>
            
                    <com.google.android.material.appbar.AppBarLayout>
                         put here your hidebale views, add to all of them :
                            app:layout_scrollFlags="scroll|enterAlways"
                        
                    </com.google.android.material.appbar.AppBarLayout>
            
                    <androidx.core.widget.NestedScrollView
        
                        put this attribute here:
                 
            app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior" />
        
                    <androidx.core.widget.NestedScrollView/>
            
                </androidx.coordinatorlayout.widget.CoordinatorLayout>
     <LinearLayout>