Search code examples
androidandroid-layoutandroid-recyclerviewandroid-collapsingtoolbarlayoutandroid-jetpack-navigation

How to fix CollapsingToolbarLayout not collapsing with RecyclerView using the Jetpack Navigation Component? (NavigationUI)


I'm setting up the app navigation with the new Jetpack Navigation Component and the NavigationUI class to support navigation within a CollapsingToolbarLayout. However it does not work using the code/method from the documentation.

I've setted up the MainActivity as shown in the documentation: LinearLayout as Parent View, within an AppBarLayout, within a CollapsingToolbarLayout, and the toolbar itself. And the host fragment.

The navigation start destination is a FrameLayout, which contains the actual RecyclerView.

I tried various layout_scrollFlags and tried to set a CoordinatorLayout as parent view instead of a LinearLayout.

activity_main.xml

<LinearLayout
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:android="http://schemas.android.com/apk/res/android"
        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">

        <com.google.android.material.appbar.CollapsingToolbarLayout
                android:id="@+id/collapsing_toolbar_layout"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                app:contentScrim="?attr/colorPrimary"
                app:expandedTitleGravity="top"
                app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">

            <androidx.appcompat.widget.Toolbar
                    android:id="@+id/toolbar"
                    android:layout_width="match_parent"
                    android:layout_height="?attr/actionBarSize"
                    android:background="?attr/colorPrimary"
                    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
                    app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
                    app:layout_collapseMode="pin"/>
        </com.google.android.material.appbar.CollapsingToolbarLayout>
    </com.google.android.material.appbar.AppBarLayout>

    <fragment
            android:id="@+id/nav_host_fragment"
            android:name="androidx.navigation.fragment.NavHostFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:defaultNavHost="true"
            app:navGraph="@navigation/nav_graph"/>
</LinearLayout>

In the MainActivity onCreate function:

// Set Toolbar as ActionBar
setSupportActionBar(findViewById(R.id.toolbar))

val layout = findViewById<CollapsingToolbarLayout>(R.id.collapsing_toolbar_layout)
val toolbar = findViewById<Toolbar>(R.id.toolbar)
val navController = findNavController(R.id.nav_host_fragment)
val appBarConfiguration = AppBarConfiguration(navController.graph)
layout.setupWithNavController(toolbar, navController, appBarConfiguration)

The first destination where I expect the collapsing behaviour:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
             xmlns:tools="http://schemas.android.com/tools"
             android:layout_width="match_parent"
             android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto"
             tools:context=".restaurant.RestaurantsFragment">

    <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/restaurant_recyclerview"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            tools:listitem="@layout/restaurant_item"/>

</FrameLayout>

I expect the toolbar collapsing while scrolling through the RecyclerView. Actual it's just static.

I think there might be a connection between the RecyclerView and the CollapsingToolbar missing? What am I missing?


Solution

  • Found a solution.

    Use CoordinatorLayout as Parent View instead of LinearLayout. Remove the CollapsingToolbarLayout. Declare layout_scrollFlags in the Toolbar (eg. app:layout_scrollFlags="scroll|enterAlways|snap"). And in the fragment View add app:layout_behavior="@string/appbar_scrolling_view_behavior" (important since we use a RecyclerView in the home Fragment)

    main_activity.xml

    <androidx.coordinatorlayout.widget.CoordinatorLayout
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:android="http://schemas.android.com/apk/res/android"
        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">
    
        <androidx.appcompat.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="?attr/colorPrimary"
                android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
                app:layout_scrollFlags="scroll|enterAlways|snap"
        />
    
    </com.google.android.material.appbar.AppBarLayout>
    
    <fragment
            android:id="@+id/nav_host_fragment"
            android:name="androidx.navigation.fragment.NavHostFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:defaultNavHost="true"
            app:navGraph="@navigation/nav_graph"
            app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
    
    </androidx.coordinatorlayout.widget.CoordinatorLayout>
    

    MainActivity onCreate

        // Set Toolbar as ActionBar
        setSupportActionBar(findViewById(R.id.toolbar))
    
        val navController = findNavController(R.id.nav_host_fragment)
        val appBarConfiguration = AppBarConfiguration(navController.graph)
        findViewById<Toolbar>(R.id.toolbar)
            .setupWithNavController(navController, appBarConfiguration)