'Hide/Show Bottom Navigation and Collapsible Toolbar on scroll in fragment

I am trying to implement show/hide behavior of bottom navigation and collapsible toolbar from a specific fragment of bottom navigation.

Here is my activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <fragment
        android:id="@+id/nav_host_fragment_activity_main"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:defaultNavHost="true"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        app:layout_constraintBottom_toTopOf="@id/nav_view"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:navGraph="@navigation/mobile_navigation" />

    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/nav_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        android:background="?android:attr/windowBackground"
        app:layout_behavior="@string/hide_bottom_view_on_scroll_behavior"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:menu="@menu/bottom_nav_menu" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

And here is the fragment_home.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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=".ui.home.HomeFragment">

    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/purple_200">

        <com.google.android.material.appbar.CollapsingToolbarLayout
            android:id="@+id/collapsing_toolbar"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            app:contentScrim="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|enterAlways|snap">

            <TextView
                android:id="@+id/text_header"
                android:layout_width="match_parent"
                android:layout_height="150dp"
                android:gravity="center"
                android:text="Parallax Area"
                android:textSize="20sp" />

        </com.google.android.material.appbar.CollapsingToolbarLayout>

    </com.google.android.material.appbar.AppBarLayout>

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="4dp"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

Screenshot

Currently when I scroll, only 'Parallax Area (pink)' is showing/hiding but not bottom navigation in sync. When I remove the '@+id/text_header' then my bottom navigation also shows/hides. I want to do it for only this fragment, not for the others. I came across with nested coordinator layout implementations, none of them worked.

How can I solve this? Thanks in advance.



Solution 1:[1]

I just found the solution to show/hide the BottomNavigation in an Activity when scrolling a RecyclerView in a Fragment. The core idea is to set HideBottomViewOnScrollBehavior programmatically when you're navigating Fragments

  1. First of all, if you're using Navigation component from Jetpack, use addOnDestinationChangedListener in the Activity witch holds the nav host to get the current showing Fragment.
navController.addOnDestinationChangedListener { _, destination, _ ->
    when (destination.id) {
        R.id.scrollToHideFragment -> {
            toggleBottomNavBehavior(true)
        }
        else -> {
            toggleBottomNavBehavior(false)
        }
    }
}

In the above code, toggleBottomNavBehavior will be called when the destination has changed.

  1. Add toggleBottomNavBehavior method in the Activity
private fun toggleBottomNavBehavior(scrollToHide: Boolean) {
    // Get the layout params of your BottomNavigation
    val layoutParams = binding.bottomNav.layoutParams as CoordinatorLayout.LayoutParams

    // Apply LayoutBehavior to the layout params
    layoutParams.behavior =
            if (scrollToHide) HideBottomViewOnScrollBehavior<CoordinatorLayout>() else null

    // Add margin to Nav Host Fragment if the layout behavior is NOT added
    // bottom_nav_height is 56dp when using Material BottomNavigation
    binding.navHostMain.updateLayoutParams<ViewGroup.MarginLayoutParams> {
            setMargins(
                0, 0, 0, if (scrollToHide) 0 else resources.getDimensionPixelSize(R.dimen.bottom_nav_height)
            )
        }
    }

Now you can scroll in a Fragment and hide the BottomNav in the Activity!

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1