问题
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 verticalLinearLayout
, so order counts;- what makes child react to scroll gestures is actually defining the
scroll
flags through theandroid: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