我有一个CoordinatorLayout
包含两个NestedScrollView
,一个有ScrollingViewBehavior
而另一个有BottomSheetBehavior
并且扮演BottomSheet
角色,问题出在我身上时拖动BottomSheet
,第一个NestedScrollView
滚动:
我的期望:
当我滚动BottomSheet
时,另一个NestedScrollView
不应滚动
我尝试了什么:
我创建了一个自定义行为并覆盖了onInterceptTouchEvent
,On BottomSheet
返回true
并在dispatchTouchEvent
上调用BottomSheet
的事件,它阻止了另一个{{1}滚动但NestedScrollView
无法自动滚动,点击BottomSheet
上的活动,儿童就不再有效了。
这是我的布局:
BottomSheet
和我的toolbar.xml:
<android.support.design.widget.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:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
tools:ignore="UnusedAttribute">
<include
layout="@layout/toolbar"/>
<android.support.v4.widget.NestedScrollView
android:id="@+id/nested"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="?actionBarSize"
android:background="#ff0"
android:fillViewport="true"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:id="@+id/ll1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingTop="24dp">
<Button
android:id="@+id/button_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:background="@android:color/holo_green_dark"
android:padding="16dp"
android:text="Button 1"
android:textColor="@android:color/white"/>
<Button
android:id="@+id/button_2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:background="@android:color/holo_blue_light"
android:padding="16dp"
android:text="Button 2"
android:textColor="@android:color/white"/>
<Button
android:id="@+id/button_3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:background="@android:color/holo_red_dark"
android:padding="16dp"
android:text="Button 3"
android:textColor="@android:color/white"/>
<android.support.v4.widget.Space
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Bottom..."/>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
<android.support.v4.widget.NestedScrollView
android:id="@+id/bottom_sheet"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/holo_orange_light"
android:clipToPadding="false"
android:elevation="4dp"
android:fillViewport="true"
app:behavior_peekHeight="60dp"
app:layout_behavior=".Behavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:elevation="6dp"
android:focusable="true"
android:padding="16dp"
android:text="@string/ipsum"
android:textSize="16sp"/>
<RecyclerView.../>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
答案 0 :(得分:6)
更新了更简单的解决方案。
您的问题的解决方案可分为两个部分:
要在不影响appbar的情况下提升底部工作表,我们需要检测底部工作表何时负责滚动并让appbar拒绝嵌套滚动,以便它不会接收后续嵌套滚动事件。这是通过AppBarLayout.Behavior
MyAppBarBehavior
方法完成的。 (请参阅下面AppBarLayout.Behavior
的代码。)
我们现在可以像一个独立的滑动面板一样向上拖动底部纸张。
现在我们已经将底部纸张拖了起来,我们可以将它拖回来吗?是的,不。如果底部工作表滚动到其内容的顶部,那么如果我们触摸底部工作表下面的,我们可以向下拖动底部工作表。如果我们触摸appbar上的底部纸张(当然,它位于底部纸张后面),那么我们就无法将底部纸张向下拖动。未经我们修改,此问题存在于基础代码中。我认为底页覆盖appbar是不寻常的。
为了演示此通知,在此视频中,当拖动底部工作表时,appbar会在底部工作表后面打开。
要更改此行为,我们会覆盖AppBarLayout.Behavior
的{{3}},如果触摸底部工作表,则返回false。
以下是新的class MyAppBarBehavior extends AppBarLayout.Behavior {
private boolean mIsSheetTouched = false;
@Override
public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child,
View directTargetChild, View target, int axes, int type) {
// Set flag if the bottom sheet is responsible for the nested scroll.
mIsSheetTouched = target.getId() == R.id.bottom_sheet;
// Only consider starting a nested scroll if the bottom sheet is not touched; otherwise,
// we will let the other views do the scrolling.
return !mIsSheetTouched
&& super.onStartNestedScroll(coordinatorLayout, child, directTargetChild,
target, axes, type);
}
@Override
public boolean onInterceptTouchEvent(CoordinatorLayout parent, AppBarLayout child, MotionEvent ev) {
// Don't accept touch stream here if the bottom sheet is touched. This will permit the
// bottom sheet to be dragged down without interaction with the appBar. Reset on cancel.
if (ev.getActionMasked() == MotionEvent.ACTION_CANCEL) {
mIsSheetTouched = false;
}
return !mIsSheetTouched && super.onInterceptTouchEvent(parent, child, ev);
}
}
:
<强> MyAppBarBehavior 强>
id
(我不应该使用特定的<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="320dp"
android:fitsSystemWindows="true"
app:layout_behavior=".MyAppBarBehavior"
app:expanded="true">
识别底页,但这只是一个演示。)
将自定义行为添加到appbar:
{{1}}
以下是最终结果:
可能还有其他方法可以实现这一目标。我可能会使用现有的滑动面板库,例如onInterceptTouchEvent
,而不是将底部工作表放在嵌套的滚动环境中,然后我们必须撤消环境的影响。