AppBarLayout child doesn't collapse when scrolling

两盒软妹~` 提交于 2019-12-05 04:59:30

问题


I have a AppBarLayout which contains an horizontal RecyclerView among its children. The sibling of the AppBarLayout is a ViewPager (which contains a vertical RecyclerView).

Here is the XML:

<android.support.design.widget.CoordinatorLayout
    android:id="@+id/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.search.SearchResultFragment">

<android.support.v4.view.ViewPager
    android:id="@+id/view_pager"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:overScrollMode="never"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"/>

<android.support.design.widget.AppBarLayout
    android:id="@+id/appBarLayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:elevation="@dimen/d2"
    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

    <LinearLayout
        android:id="@+id/header_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:background="@color/white"
        android:gravity="center_vertical"
        android:orientation="horizontal">

        <ImageView
            android:id="@+id/back_image_view"
            android:layout_width="?attr/actionBarSize"
            android:layout_height="?attr/actionBarSize"
            android:scaleType="center"
            android:src="@drawable/ic_backarrow_gray"/>

        <android.support.v7.widget.RecyclerView
            android:id="@+id/query_terms_recycler_view"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_gravity="center_vertical"
            android:layout_weight="1"/>

        <ImageView
            android:id="@+id/search_image_view"
            android:layout_width="?attr/actionBarSize"
            android:layout_height="?attr/actionBarSize"
            android:scaleType="center"
            android:src="@drawable/ic_search_gray"/>

    </LinearLayout>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/related_terms_recycler_view"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="@color/search_term_bg"
        app:layout_scrollFlags="scroll|enterAlways"/>

    <android.support.design.widget.TabLayout
        android:id="@+id/tab_layout"
        android:layout_width="match_parent"
        android:layout_height="@dimen/d8"
        android:background="@color/tab_and_nav_bar"/>

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

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

I already have another UI with AppBarLayout which is able to respond to scroll successfully with a Toolbar . The code is pretty much the same, but in this case something is wrong because the RecyclerView is not collapsing / hiding.


回答1:


  • AppBarLayout is just a vertical LinearLayout, so order counts;
  • what makes child react to scroll gestures is actually defining the scroll flags through the android:layout_scrollFlags attribute.

From the official documentation for that flag, we can read that

The view will be scroll in direct relation to scroll events. This flag needs to be set for any of the other flags to take effect. If any sibling views before this one do not have this flag, then this value has no effect.

That means that your flag is ignored because the other childs do not have any flags. I believe the reason behind this is that we want only the top views to be hidden - bottom views can't disappear if there's still something above.

So the solution in this case (which you might not like) is to, either:

  • move that view to the top, so it will be the only view exiting;
  • give all views the scroll flag. They'll react together to scroll gestures, which might not be what you want.

    <AppBarLayout>
        <RecyclerView ...
            android:layout_scrollFlags="scroll|enterAlways"/>
    
        <LinearLayout ... >
        <TabLayout ... >
    </AppBarLayout>
    



回答2:


Big thanks to @m vai for the tips

I solved this problem customising the behaviour of the AppBarLayout Here is the code:

private void setAppBarLayoutBehaviour() {
    AppBarLayout.Behavior behavior = new AppBarLayout.Behavior() {

        @Override
        public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child, View directTargetChild, View target, int nestedScrollAxes) {
            // Trigger the following events if it is a vertical scrolling
            return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL || super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes);
        }

        @Override
        public void onNestedScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
            super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);

            // If I slowly reach the top, without fling, show the RecyclerView
            int[] firstVisiblePositions = ((StaggeredGridLayoutManager) ((RecyclerView) target).getLayoutManager()).findFirstCompletelyVisibleItemPositions(null);
            for (int position : firstVisiblePositions) {
                if (position == 0) {
                    showRelatedTerms();
                    break;
                }
            }
        }

        @Override
        public boolean onNestedFling(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, float velocityX, float velocityY, boolean consumed) {
            if (velocityY > 500) {
                // Hide the RecyclerView
            } else if (velocityY < -500) {
                // Show the recyclerView
            }
            return true;
        }
    };
    ((CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams()).setBehavior(behavior);
}

And I didn't apply any scrollFlags in the XML.



来源:https://stackoverflow.com/questions/31112339/appbarlayout-child-doesnt-collapse-when-scrolling

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!