androidandroid-layoutandroid-tablayoutandroid-coordinatorlayoutandroid-appbarlayout

Tab Layout only collapsing on fling, not on slow scroll


for the below layout, when I scroll the content up on a page within the viewpager... if I keep my finger on the screen and scroll up slowly, the tab layout doesn't collapse into the toolbar but if I fling the content up, it does. Any ideas why?

activity_home.xml

    <layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".newnav.home.HomeActivity">

    <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
        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:context=".newnav.NavigationActivity">

        <!-- Check whether do we need this surface view still? -->
        <SurfaceView
            android:id="@+id/surfaceView"
            android:layout_width="0dp"
            android:layout_height="0dp" />

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <com.my.package.view.MyToolBar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignParentTop="true"
                android:background="@color/primary_color" />

            <FrameLayout
                android:id="@+id/fragment_container"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_below="@id/toolbar" />

            <com.my.package.view.SomeCustomView
                android:id="@+id/breaking_news_view"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignParentTop="true" />
        </RelativeLayout>

        <com.my.package.navigation.NavigationLayout
            android:id="@+id/navigation_layout"
            android:layout_width="320dp"
            android:layout_height="match_parent"
            android:layout_gravity="start"
            android:background="@android:color/white"
            android:fitsSystemWindows="true" />
    </android.support.v4.widget.DrawerLayout>
</layout>

fragment_home.xml (parent layout has the toolbar):

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

    <android.support.design.widget.CoordinatorLayout
        android:id="@+id/coordinatorLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.design.widget.AppBarLayout
            android:id="@+id/appBarLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/white"
            android:fitsSystemWindows="true"
            app:layout_behavior="com.nbc.news.newnav.home.NbcTabBarScrollingBehavior">

            <android.support.design.widget.TabLayout
                android:id="@+id/tabLayout"
                style="@style/HomeTabDesign"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@drawable/top_nav_tab_bg"
                app:tabBackground="@color/transparent"
                android:elevation="4dp"
                android:minHeight="@dimen/tab_layout_height"
                app:layout_scrollFlags="scroll|enterAlways"
                app:tabGravity="fill"
                app:tabIndicatorColor="@color/home_tab_strip_color"
                app:tabIndicatorHeight="3dp"
                app:tabMaxWidth="0dp"
                app:tabMode="fixed"
                app:tabSelectedTextColor="@color/home_tab_text_color_selected"
                app:tabTextColor="@color/home_tab_text_color_normal" />

        </android.support.design.widget.AppBarLayout>

        <com.my.package.view.MyViewPager
            android:id="@+id/viewPager"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior" />
    </android.support.design.widget.CoordinatorLayout>
</layout>

section_fragment.xml (the view that scrolls):

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

    <com.my.package.view.ProgressiveFrameLayout
        android:id="@+id/progressiveLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/divider_white"
        app:contentLayoutId="@id/contentLayout">

        <FrameLayout
            android:id="@+id/contentLayout"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <android.support.v4.widget.SwipeRefreshLayout
                android:id="@+id/swipeRefreshLayout"
                android:layout_width="match_parent"
                android:layout_height="match_parent">

                <android.support.v7.widget.RecyclerView
                    android:id="@+id/sectionRecyclerView"
                    android:layout_width="match_parent"
                    android:descendantFocusability="blocksDescendants"
                    android:layout_height="match_parent"
                    android:background="@android:color/white" />
            </android.support.v4.widget.SwipeRefreshLayout>

            <FrameLayout
                android:id="@+id/adContainer"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_gravity="bottom|center_horizontal" />
        </FrameLayout>

    </com.nbc.news.view.ProgressiveFrameLayout>
</layout>

Solution

  • The old answer

    This solution did not work in the case. But it may be helpful to others.

    You have not provided the necessary part of your code. However I strongly suspect that you are using an intermediate layout between the SwipeRefreshLayout and your Recyclerview (or ListView). In other words, SwipeRefreshLayout is not the direct parent of Recyclerview. Fix it and it will work.


    If you want to know what really happens in the background

    If you check the android source code, you can find a method canSwipeRefreshChildScrollUp(). It is responsible to decide whether it is possible for the child view of this layout to scroll up. It is required to override this if the child view is a custom view.

    public boolean canChildScrollUp() {
            if (mChildScrollUpCallback != null) {
                return mChildScrollUpCallback.canChildScrollUp(this, mTarget);
            }
            if (android.os.Build.VERSION.SDK_INT < 14) {
                if (mTarget instanceof AbsListView) {
                    final AbsListView absListView = (AbsListView) mTarget;
                    return absListView.getChildCount() > 0
                            && (absListView.getFirstVisiblePosition() > 0 || absListView.getChildAt(0)
                                    .getTop() < absListView.getPaddingTop());
                } else {
                    return ViewCompat.canScrollVertically(mTarget, -1) || mTarget.getScrollY() > 0;
                }
            } else {
                return ViewCompat.canScrollVertically(mTarget, -1);
            }
        }
    

    If you use an intermediate view, the swipe refresh layout will assume that it is the target (see mTarget in the 6th line of the method) and the default implementation of that view return false always which will lead to this problem.

    New answer

    CoordinatorLayout"s child should implement NestedScrollingChild interface. So, try wrapping your FrameLayout in a NestedScrollView