在 AppBarLayout 折叠之前防止 RecyclerView 在 AppBarLayout 下滚动
Prevent RecyclerView from scrolling under AppBarLayout before AppBarLayout is collapsed
-
android
-
android-support-library
-
android-design-library
-
android-coordinatorlayout
-
android-appbarlayout
我正在创建一个带有 header 的 RecyclerView
,当您向上滚动 RecyclerView
时,header 会折叠。我可以通过下面的布局非常接近地实现这一点,透明 AppBarLayout
和 MyCoolView
即 header。视差效果很好
但是,如果 header 仍然可见并且我使用 RecyclerView
,RV 会缓慢滚动到顶部并且一些项目在工具栏下方,直到 RV 到达顶部风景。我一直在玩 scrollFlags
但没有取得理想的结果。关于如何改善投掷体验以免项目被剪裁的任何建议?
观看视频并观看它的一闪而过--- 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() 返回,可能会导致堆栈溢出。可以用布尔值或 removing/adding 滚动侦听器
来解决
- 可能您不仅希望在 AppBarLayout 完全展开时防止滚动,而且更普遍地希望在 AppBarLayout 未折叠时防止滚动。这意味着您不必检查
offset != 0
,而是检查 offset == appBarLayout.getTotalScrollRange()
。我觉得。
也许你可以像这样将 layout_behavior="@string/appbar_scrolling_view_behavior" 添加到你的 RecylerView。
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" />
在 FrameLayout 中包装 RecyclerView 解决了这个问题。
您还需要将 appbar_scrolling_view_behavior 从 RecyclerView 移动到 FrameLayout,以便它正确定位在 AppBarLayout 下方。
<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>
<!-- BEGIN SOLUTION -->
<!-- the layout behavior needs to be set on the FrameLayout, not the RecyclerView -->
<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>
<!-- END SOLUTION -->
</android.support.design.widget.CoordinatorLayout>
android
android-support-library
android-design-library
android-coordinatorlayout
android-appbarlayout
我正在创建一个带有 header 的 RecyclerView
,当您向上滚动 RecyclerView
时,header 会折叠。我可以通过下面的布局非常接近地实现这一点,透明 AppBarLayout
和 MyCoolView
即 header。视差效果很好
但是,如果 header 仍然可见并且我使用 RecyclerView
,RV 会缓慢滚动到顶部并且一些项目在工具栏下方,直到 RV 到达顶部风景。我一直在玩 scrollFlags
但没有取得理想的结果。关于如何改善投掷体验以免项目被剪裁的任何建议?
观看视频并观看它的一闪而过--- 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() 返回,可能会导致堆栈溢出。可以用布尔值或 removing/adding 滚动侦听器 来解决
- 可能您不仅希望在 AppBarLayout 完全展开时防止滚动,而且更普遍地希望在 AppBarLayout 未折叠时防止滚动。这意味着您不必检查
offset != 0
,而是检查offset == appBarLayout.getTotalScrollRange()
。我觉得。
也许你可以像这样将 layout_behavior="@string/appbar_scrolling_view_behavior" 添加到你的 RecylerView。
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" />
在 FrameLayout 中包装 RecyclerView 解决了这个问题。
您还需要将 appbar_scrolling_view_behavior 从 RecyclerView 移动到 FrameLayout,以便它正确定位在 AppBarLayout 下方。
<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>
<!-- BEGIN SOLUTION -->
<!-- the layout behavior needs to be set on the FrameLayout, not the RecyclerView -->
<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>
<!-- END SOLUTION -->
</android.support.design.widget.CoordinatorLayout>