FindOutIslamNow
FindOutIslamNow

Reputation: 1236

CollapsingToolbarLayout causes RecyclerView's bottom to be underscreen

I have AppBarLayout with fixed height (@dimen/app_bar_height = 200dp), which has CollapsingToolbarLayout in it. When scrolling down, part of recyclerview is hidden under screen bottom.

If I remove scroll flags (ie. disable scrolling collapse) I remove app:layout_scrollFlags="scroll|exitUntilCollapsed|snap" from CollapsingToolbarLayout then it is normally aligning screen bottom.

<?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"
    android:fitsSystemWindows="true"
    tools:ignore="MergeRootFrame">

    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/app_bar"
        android:layout_width="match_parent"
        android:layout_height="@dimen/app_bar_height"
        android:fitsSystemWindows="true"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

            <!-- Problem HERE in app:layout_scrollFlags -->
        <com.google.android.material.appbar.CollapsingToolbarLayout
            android:id="@+id/toolbar_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            app:expandedTitleGravity="bottom"
            app:contentScrim="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|exitUntilCollapsed|snap" 
            app:toolbarId="@+id/toolbar">

            <TextView
                android:text="Hello, Hello, Hello, Hello, Hello, Hello, Hello, Hello, Hello, Hello"
                android:textSize="19sp"
                android:textStyle="bold"
                android:id="@+id/txtDescr"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:layout_collapseMode="parallax"
                app:layout_collapseParallaxMultiplier="0.5"/>

            <androidx.appcompat.widget.Toolbar
                android:id="@+id/detail_toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:layout_collapseMode="pin"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />

            <com.google.android.material.floatingactionbutton.FloatingActionButton
                android:id="@+id/fab"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_vertical|start"
                android:layout_margin="@dimen/fab_margin"
                app:layout_collapseMode="pin"
                app:srcCompat="@android:drawable/stat_notify_chat" />

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

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

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:scrollbars="vertical"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        android:scrollbarThumbVertical="@android:color/darker_gray"
        android:scrollbarSize="7dp"
        android:layout_height="match_parent"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

Upvotes: 3

Views: 1466

Answers (4)

devrocca
devrocca

Reputation: 2547

My guess is that you are loading the items in the RecyclerView too soon, before the CoordinatorLayout has finished measuring the AppbarLayout. This may happen if you have your list of items immediately available in your onViewCreated and you create and assign your adapter right away. I don't know how you setup your RecyclerView in your code, but I had this same problem and I solved it by using View.post(Runnable):

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    val adapter = MyAdapter(viewModel.items)
    // replace:
    // recyclerView.adapter = adapter
    // with:
    view.post { recyclerView.adapter = adapter }
}

Also note that if you happened to use a subclass of ListAdapter, which works asynchronously from the main thread, infact you would likely not have had this issue.

Upvotes: 1

FindOutIslamNow
FindOutIslamNow

Reputation: 1236

I ended up using the followiing, to detect last item scroll and notifyDataSetChanged(), that solves the issue :

    recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {

        private boolean hasFixedLastItemNotVisible = false;

        @Override
        public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);

            if (!hasFixedLastItemNotVisible &&
                    !recyclerView.canScrollVertically(10) &&
                    newState==RecyclerView.SCROLL_STATE_IDLE) {
                hasFixedLastItemNotVisible = true;
                recyclerView.getAdapter().notifyDataSetChanged();
            }
        }
    });

Upvotes: 1

Wini
Wini

Reputation: 1986

when scrolling down recycleview....if you dont want a toolbar as recycleview is getting hidden behind toolbar....

use this--> app:layout_scrollFlags="scroll|enterAlways|enterAlwaysCollapsed"

so your collapsingtoolbarlayout code will be-->

 <com.google.android.material.appbar.CollapsingToolbarLayout
        android:layout_width="match_parent"
        android:layout_height="350dp"
        app:layout_scrollFlags="scroll|enterAlways|enterAlwaysCollapsed"
        app:contentScrim="?attr/colorPrimary"
        app:expandedTitleTextAppearance="@android:color/transparent"
        android:fitsSystemWindows="true"
        >

Upvotes: 0

Parag Pawar
Parag Pawar

Reputation: 857

Tried your code multiple times with no luck. Finally found a workaround. Just add the height of view which you want to pin at the top as margin-bottom to the recyclerView keeping recyclerView's height as wrap_content.

For Ex. If you want to pin your toolbar then add it's height as margin-bottom to the recycler view

<androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:scrollbars="vertical"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        android:scrollbarThumbVertical="@android:color/darker_gray"
        android:scrollbarSize="7dp"
        android:layout_height="wrap_content"
        android:layout_marginBottom="?attr/actionBarSize"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />

Hope this solves your problem.

Upvotes: 3

Related Questions