如何在 CoordinatorLayout 中禁用 AppBarLayout 的滚动?
Posted
技术标签:
【中文标题】如何在 CoordinatorLayout 中禁用 AppBarLayout 的滚动?【英文标题】:How to disable scrolling of AppBarLayout in CoordinatorLayout? 【发布时间】:2016-03-10 13:49:23 【问题描述】:我有MapFragment
内部AppBarLayout
有视差效果:
我想在AppBarLayout
上禁用滚动,因为无法跨地图移动,因为地图上的触摸事件总是作为滚动事件处理。
我想通过滚动屏幕底部的RecyclerView
来处理AppBarLayout
的折叠。
这是我的 xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
android:layout_
android:layout_
android:fitsSystemWindows="true"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/collapsing_toolbar"
android:layout_
android:layout_
android:fitsSystemWindows="true"
app:contentScrim="@color/white"
app:expandedTitleMarginEnd="64dp"
app:expandedTitleMarginStart="48dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
app:titleEnabled="false">
<FrameLayout
android:layout_
android:layout_
app:layout_collapseMode="parallax"
android:fitsSystemWindows="true">
<fragment
android:id="@+id/map"
android:name="com.androidmapsextensions.SupportMapFragment"
android:layout_
android:layout_ />
</FrameLayout>
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_
android:layout_
app:contentInsetLeft="0dp"
app:contentInsetStart="0dp"
app:layout_collapseMode="pin"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light">
<include
android:id="@+id/search_bar"
layout="@layout/layout_searchbar" />
</android.support.v7.widget.Toolbar>
<View
android:id="@+id/toolbar_shadow"
android:layout_
android:layout_
android:layout_below="@id/search_bar"
android:layout_gravity="bottom"
android:background="@drawable/toolbar_dropshadow"
android:visibility="gone" />
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<RecyclerView
android:id="@+id/farm_list"
android:layout_
android:layout_
android:background="@android:color/transparent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
感谢您的回复。
【问题讨论】:
你的CoordinatorLayout
在哪里?
【参考方案1】:
我不确定我明白了,但我认为您正在寻找DragCallback
。
DragCallback
接口允许选择是否应通过滚动到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;
);
通过始终返回false
,您的滚动视图将不再受 ABL 控制。
注意:在调用它之前,您应该检查ViewCompat.isLaidOut(appBarLayout)
,否则params.getBehavior()
将返回null。
【讨论】:
实际上我在上面添加的解决方案可以解决问题,但还是感谢您的帮助。我很好奇,所以我会试一试:) 将 onInterceptTouchEvent 设置为 coordinator 将来可能会给您带来一些问题。这是“官方”解决方案(如果我有你的问题)。 无法使用此解决方案。请您再解释一下好吗?谢谢 返回给我的“行为”变量为空。你是如何让它工作的? 我在访问 params.getBehavior 时得到了 null。这个答案 (***.com/a/33230473/6117565) 是改变行为的另一种方式,它对我有用:【参考方案2】:问题
-
即使滚动内容适合屏幕,AppBarLayout 也会滚动。
这是因为默认情况下我们可以通过触摸&拖动AppBarLayout来拖动AppBarLayout。
解决方案
我们将禁用 AppBarLayout 的“拖动”行为。
// Disable "Drag" for AppBarLayout (i.e. User can't scroll appBarLayout by directly touching appBarLayout - User can only scroll appBarLayout by only using scrollContent)
if (appBarLayout.getLayoutParams() != null)
CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams();
AppBarLayout.Behavior appBarLayoutBehaviour = new AppBarLayout.Behavior();
appBarLayoutBehaviour.setDragCallback(new AppBarLayout.Behavior.DragCallback()
@Override
public boolean canDrag(@NonNull AppBarLayout appBarLayout)
return false;
);
layoutParams.setBehavior(appBarLayoutBehaviour);
参考
这只是上面“natario”接受的答案的扩展。
https://developer.android.com/reference/android/support/design/widget/AppBarLayout.Behavior.DragCallback.html
【讨论】:
嗨瓦桑斯!当他滚动到recyclerview时,我想禁用用户滚动(CoordinatorLayout)。请问我该怎么做?【参考方案3】:您可以通过在 xml 中定义自定义 app:layout_behavior
来完成此操作。使用这种方法,您不必担心获取对LayoutParams
的引用并进行空值检查。
<android.support.design.widget.AppBarLayout
android:id="@+id/app_bar_layout"
android:layout_
android:layout_
app:layout_behavior="com.yourcompany.FixedAppBarLayoutBehavior"
>
然后创建一个从AppBarLayout.Behavior
扩展的自定义类。
public class FixedAppBarLayoutBehavior extends AppBarLayout.Behavior
public FixedAppBarLayoutBehavior(Context context, AttributeSet attrs)
super(context, attrs);
setDragCallback(new DragCallback()
@Override public boolean canDrag(@NonNull AppBarLayout appBarLayout)
return false;
);
更新为 Kotlin 版本:
class FixedAppBarLayoutBehavior(context: Context, attrs: AttributeSet) : AppBarLayout.Behavior(context, attrs)
init
setDragCallback(object : DragCallback()
override fun canDrag(appBarLayout: AppBarLayout): Boolean = false
)
【讨论】:
【参考方案4】:所以经过两个小时的尝试,我找到了一个非常简单的解决方案。我只需要扩展 CoordinatorLayout
并覆盖 OnInterceptTouchEvent
方法,因此类看起来像这样:
public class NonTouchableCoordinatorLayout extends CoordinatorLayout
public NonTouchableCoordinatorLayout(Context context, AttributeSet attrs)
super(context, attrs);
@Override
public boolean onInterceptTouchEvent(MotionEvent ev)
return false;
【讨论】:
【参考方案5】:您可以使用NestedScrollView.setNestedScrollingEnabled(false)
禁用 AppBarLayout nestScroll 事件
【讨论】:
您仍然可以通过在应用栏区域上拖动手指来滚动/展开应用栏。以上是关于如何在 CoordinatorLayout 中禁用 AppBarLayout 的滚动?的主要内容,如果未能解决你的问题,请参考以下文章
如何在折叠布局下的 CoordinatorLayout 中正确对齐元素?
如何将 CoordinatorLayout 内容滚动到顶部?