Android AppBarLayout子级不';滚动时不要折叠

Android AppBarLayout子级不';滚动时不要折叠,android,android-support-library,android-design-library,android-appbarlayout,Android,Android Support Library,Android Design Library,Android Appbarlayout,我有一个AppBarLayout,它的子级中包含一个水平RecyclerView。 AppBarLayout的同级是一个ViewPager(它包含一个垂直的RecyclerView) 以下是XML: <android.support.design.widget.CoordinatorLayout android:id="@+id/coordinatorLayout" xmlns:android="http://schemas.android.com/apk/res/andr

我有一个
AppBarLayout
,它的子级中包含一个水平
RecyclerView
AppBarLayout
的同级是一个
ViewPager
(它包含一个垂直的
RecyclerView

以下是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>

我已经有了另一个带有
AppBarLayout
的UI,它能够通过
工具栏成功响应滚动。代码基本相同,但在本例中出现了一些错误,因为
RecyclerView
没有折叠/隐藏。

  • AppBarLayout
    只是一个垂直的
    LinearLayout
    ,因此订单计数
  • 让孩子对滚动手势做出反应的实际上是通过
    android:layout\u scrollFlags
    属性定义
    scroll
    标志
从那面旗帜的背面,我们可以看到

该视图将与滚动事件直接相关。这面旗 需要设置其他任何标志才能生效。如果有的话 在此之前的同级视图没有此标志,则此值 没有效果

这意味着您的标志将被忽略,因为其他孩子没有任何标志。我相信这背后的原因是,我们只希望顶部视图被隐藏-底部视图不能消失,如果仍然有上面的东西

因此,本例中的解决方案(您可能不喜欢)是:

  • 将该视图移动到顶部,使其成为唯一退出的视图
  • 为所有视图设置
    滚动
    标志。他们会一起对滚动手势做出反应,这可能不是你想要的

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

    • 非常感谢@m vai提供的提示

      我通过自定义
      AppBarLayout
      代码如下:

      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);
      }
      
      private void setAppBarLayoutBehavior(){
      AppBarLayout.Behavior=新建AppBarLayout.Behavior(){
      @凌驾
      公共布尔值onStartNestedScroll(CoordinatorLayout CoordinatorLayout,AppBarLayout子级,View directTargetChild,View target,int nestedScrollAxes){
      //如果是垂直滚动,则触发以下事件
      返回NestedScrollAxis==ViewCompat.SCROLL_AXIS_VERTICAL | | super.onStartNestedScroll(坐标布局、子项、directTargetChild、目标、NestedScrollAxis);
      }
      @凌驾
      public void onNestedScroll(坐标布局坐标布局,AppBarLayout子对象,视图目标,int-dxConsumed,int-dyConsumed,int-dxUnused,int-dyUnused){
      super.onNestedScroll(协调布局、子项、目标、dxConsumed、dyConsumed、dxUnconsumed、dyUnconsumed);
      //如果我毫不犹豫地慢慢爬到山顶,请展示回收视图
      int[]firstVisiblePositions=((StaggedGridLayoutManager)((RecyclerView)目标)。getLayoutManager())。FindFirstVisibleItemPositions(null);
      用于(内部位置:第一个可见位置){
      如果(位置==0){
      showRelatedTerms();
      打破
      }
      }
      }
      @凌驾
      公共布尔onNestedFling(CoordinatorLayout CoordinatorLayout,AppBarLayout子级,视图目标,浮点速度yx,浮点速度yy,布尔消耗){
      如果(速度Y>500){
      //隐藏回收视图
      }否则如果(速度Y<-500){
      //显示回收视图
      }
      返回true;
      }
      };
      ((CoordinatorLayout.LayoutParams)appBarLayout.getLayoutParams()).setBehavior(行为);
      }
      

      我没有在XML中应用任何
      scrollFlags

      您的详细问题是什么?它只是对滚动手势没有响应。它应该隐藏回收器视图,但不会发生任何事情。我相信“可滚动”(可隐藏)视图必须位于顶部。如果将RecyclerView移到LinearLayout之前,是否有效?我的意思是AppBarLayout的内容应为1。RecyclerView(带滚动标志);2线性布局;3.表格布局。这样行吗?嘿,我正在努力。我将在下面回复您的答案。它几乎可以正常工作。谢谢:)我将
      RecyclerView
      移到顶部。我没有给其他孩子留下任何
      滚动标记
      。结果与预期一样:
      RecylerView
      将向外滚动,其他视图保持可见。唯一的问题是,通过设计,
      RecyclerView
      应该保持在
      线性布局
      表格布局
      之间:(有什么想法吗?也许也可以让线性布局滚动?是的,它肯定会工作,但问题是:如果我想要这样的布局怎么办?我的意思是一个顶部线性布局,一个回收器视图和一个选项卡布局,我只需要回收器视图来对滚动事件做出反应?我猜这种方法不允许我创建这种布局。你认为呢?然后你呢无法使用AppBarLayout完成此操作。想到的解决方案是为该RecyclerView和override
      onNestedScroll()
      定义自定义
      行为。在这里,当用户向下滚动时,您可以使RV不可见(
      setVisibility(View.GONE)
      );当向上滚动时,您可以使其再次可见(
      setVisibility)(View.VISIBLE)
      )。如果您确实需要,请尝试搜索“自定义行为”示例。谢谢。我自定义了该行为,但我用了另一种方式:)