在 CollapsingToolbarLayout / AppBarLayout 中禁用垂直滚动
Disable vertical scroll in CollapsingToolbarLayout / AppBarLayout
我希望仅当 scroll/touch 事件发生在 nestedscrollview 中时,CollapsingToolbarLayout / AppBarLayout 上的垂直滚动(这是有效的),但如果用户试图直接滚动 CollapsingToolbarLayout / AppBarLayout 它不应该工作。我需要这个,因为那里的 scroll/touch 事件干扰了我的 recyclerview 滚动事件。
我有这样的结构:
CoordinatorLayout
-- AppBarLayout
---- CollapsingToolbarLayout (scrollflags: scroll, exitUntilCollapsed, snap)
------ Toolbar (CollapseMode: pin)
------ RecyclerView (Horizontal, CollapseMode: pin)
----- /CollapsingToolbarLayout
-- /AppBarLayout
-- NestedScrollView (Behaviour: appbar_scrolling_view_behavior)
-- /NestedScrollView
/ CoordinatorLayout
我尝试为 CollapsingToolbarLayout / AppBarLayout 覆盖 onTouch() 和 onInterceptTouchEvent() 但它一直拦截触摸 event/scroll。
好的,我找到了解决方案。
您只需覆盖 AppBarLayout 行为中的 onDrag() 方法,如果触摸发生在 AppBarLayout 视图顶部,则不会触发滚动。
CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams();
AppBarLayout.Behavior behavior = (AppBarLayout.Behavior) params.getBehavior();
behavior.setDragCallback(new AppBarLayout.Behavior.DragCallback() {
@Override
public boolean canDrag(@NonNull AppBarLayout appBarLayout) {
return false;
}
});
这里的解决方案:
如果你 运行 因为空行为而进入 NullPointerException,你应该先分配一个:
CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) mAppbar.getLayoutParams();
params.setBehavior(new AppBarLayout.Behavior());
我为nsL的回答写了一个BindingAdapter:
@BindingAdapter("scrollable")
fun setScrollable(appBarLayout: AppBarLayout, scrollable: Boolean) {
val layoutParams = appBarLayout.layoutParams as CoordinatorLayout.LayoutParams
val behavior = (layoutParams.behavior as? AppBarLayout.Behavior) ?: AppBarLayout.Behavior()
behavior.setDragCallback(object : AppBarLayout.Behavior.DragCallback() {
override fun canDrag(appBarLayout: AppBarLayout): Boolean = scrollable
})
layoutParams.behavior = behavior
}
您可以像这样在数据绑定布局中使用它:
<com.google.android.material.appbar.AppBarLayout
...
app:scrollable="@{true/false}"
... >
...
</com.google.android.material.appbar.AppBarLayout>
在我的例子中,我还想禁用 NestedScrollView 上的滚动,这就是我编写第二个 BindingAdapter 的原因:
@BindingAdapter("scrollable")
fun setScrollable(nestedScrollView: NestedScrollView, scrollable: Boolean) {
nestedScrollView.setOnTouchListener { _, _ -> !scrollable }
}
如果您设置了 app:layout_scrollFlags
中的任何一项(如下例)- 删除它们。
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
我希望仅当 scroll/touch 事件发生在 nestedscrollview 中时,CollapsingToolbarLayout / AppBarLayout 上的垂直滚动(这是有效的),但如果用户试图直接滚动 CollapsingToolbarLayout / AppBarLayout 它不应该工作。我需要这个,因为那里的 scroll/touch 事件干扰了我的 recyclerview 滚动事件。
我有这样的结构:
CoordinatorLayout
-- AppBarLayout
---- CollapsingToolbarLayout (scrollflags: scroll, exitUntilCollapsed, snap)
------ Toolbar (CollapseMode: pin)
------ RecyclerView (Horizontal, CollapseMode: pin)
----- /CollapsingToolbarLayout
-- /AppBarLayout
-- NestedScrollView (Behaviour: appbar_scrolling_view_behavior)
-- /NestedScrollView
/ CoordinatorLayout
我尝试为 CollapsingToolbarLayout / AppBarLayout 覆盖 onTouch() 和 onInterceptTouchEvent() 但它一直拦截触摸 event/scroll。
好的,我找到了解决方案。
您只需覆盖 AppBarLayout 行为中的 onDrag() 方法,如果触摸发生在 AppBarLayout 视图顶部,则不会触发滚动。
CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams();
AppBarLayout.Behavior behavior = (AppBarLayout.Behavior) params.getBehavior();
behavior.setDragCallback(new AppBarLayout.Behavior.DragCallback() {
@Override
public boolean canDrag(@NonNull AppBarLayout appBarLayout) {
return false;
}
});
这里的解决方案:
如果你 运行 因为空行为而进入 NullPointerException,你应该先分配一个:
CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) mAppbar.getLayoutParams();
params.setBehavior(new AppBarLayout.Behavior());
我为nsL的回答写了一个BindingAdapter:
@BindingAdapter("scrollable")
fun setScrollable(appBarLayout: AppBarLayout, scrollable: Boolean) {
val layoutParams = appBarLayout.layoutParams as CoordinatorLayout.LayoutParams
val behavior = (layoutParams.behavior as? AppBarLayout.Behavior) ?: AppBarLayout.Behavior()
behavior.setDragCallback(object : AppBarLayout.Behavior.DragCallback() {
override fun canDrag(appBarLayout: AppBarLayout): Boolean = scrollable
})
layoutParams.behavior = behavior
}
您可以像这样在数据绑定布局中使用它:
<com.google.android.material.appbar.AppBarLayout
...
app:scrollable="@{true/false}"
... >
...
</com.google.android.material.appbar.AppBarLayout>
在我的例子中,我还想禁用 NestedScrollView 上的滚动,这就是我编写第二个 BindingAdapter 的原因:
@BindingAdapter("scrollable")
fun setScrollable(nestedScrollView: NestedScrollView, scrollable: Boolean) {
nestedScrollView.setOnTouchListener { _, _ -> !scrollable }
}
如果您设置了 app:layout_scrollFlags
中的任何一项(如下例)- 删除它们。
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"