在AppBarLayout折叠之前防止RecyclerView在AppBarLayout下滚动

问题描述:

我正在创建一个RecyclerView头部,其中当您向上滚动RecyclerView时,头部会折叠。我可以通过下面的布局非常仔细地实现这一点,透明的AppBarLayoutMyCoolView这是标题。视差效果很好。在AppBarLayout折叠之前防止RecyclerView在AppBarLayout下滚动

但是,如果标题仍然可见,并且我打开RecyclerView,RV会慢慢滚动到顶部,并且其中一些项目位于工具栏下方,直到RV到达视图的顶部。我一直在玩scrollFlags,但没有取得理想的结果。有关如何改善投掷经验以便物品不被剪裁的任何建议?

查看视频和flinged当观看--- https://www.dropbox.com/s/jppd6m7zo41k23z/20160609_151309.mp4?dl=0

<android.support.design.widget.CoordinatorLayout> 

    <android.support.design.widget.AppBarLayout 
     android:background="#00000000"> 

     <android.support.design.widget.CollapsingToolbarLayout 
      app:layout_scrollFlags="scroll|exitUntilCollapsed"> 

      <com.android.myapp.MyCoolView 
       app:layout_collapseMode="parallax"/> 

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

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

    <android.support.v7.widget.RecyclerView/> 

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

可能的解决方法(未经测试)。将OnOffsetChangedListener添加到您的AppBarLayout,并记录偏移值。首先,声明该字段:

private boolean shouldScroll = false; 

然后的onCreate:

AppBarLayout appbar = findViewById(...); 
appbar.addOnOffsetChangedListener(new OnOffsetChangedListener() { 
    @Override 
    void onOffsetChanged(AppBarLayout appbar, int offset) { 
     // Allow recycler scrolling only if we started collapsing. 
     this.shouldScroll = offset != 0; 
    } 
}); 

现在,添加滚动收听到您的RecyclerView。每当它试图滚动,恢复滚动如果AppBarLayout仍在扩大:

RecyclerView recycler = findViewById(...); 
recycler.addOnScrollListener(new OnScrollListener() { 
    @Override 
    void onScrolled(RecyclerView recycler, int dx, int dy) { 
     // If AppBar is fully expanded, revert the scroll. 
     if (!shouldScroll) { 
      recycler.scrollTo(0,0); 
     } 
    } 
}); 

这可能需要一些调整,但。我看到两个问题:

  • 如果scrollTo()调用onScrolled()返回,可能的堆栈溢出。可以通过布尔值或删除/添加滚动监听器来解决
  • 可能您希望不仅在AppBarLayout完全展开时防止滚动,而且通常在AppBarLayout未折叠时防止滚动。这意味着您不必检查offset != 0,而是检查offset == appBarLayout.getTotalScrollRange()。我认为。
+0

这工作得很好。偏移总是小于零,除非完全展开。所以'offset> 0'将不起作用。我做了一些像'shouldScroll = appbar.getTotalScrollRange()== Math.abs(offset)'。没有得到*,所以它似乎工作。 – ono

+0

是的,我忘了它是否定的。你做得对。 – natario

+0

这对我来说根本不起作用。有没有人找到解决方案?它使appbarlayout边界线不可用。 –

也许你可以像这样向你的RecylerView添加layout_behavior =“@ string/appbar_scrolling_view_behavior”。

<android.support.v7.widget.RecyclerView 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" /> 
+0

我有。我忘了将它包含在上面的xml中 – ono

结束语中的FrameLayout的RecyclerView解决了这个问题。

您还需要将appbar_scrolling_view_behavior从RecyclerView移动到FrameLayout,以便将其正确放置在AppBarLayout下方。

<FrameLayout 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    app:layout_behavior="@string/appbar_scrolling_view_behavior" 
    > 

    <!--This RecyclerView MUST be wrapped in a FrameLayout--> 
    <!--This prevents the RecyclerView from going behind the AppBarLayout--> 
    <android.support.v7.widget.RecyclerView 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     /> 

</FrameLayout>