防止在Bottom Sheet祖先视图中滚动

时间:2018-03-05 08:09:23

标签: android android-layout android-coordinatorlayout bottom-sheet android-nestedscrollview

我有一个CoordinatorLayout包含两个NestedScrollView,一个有ScrollingViewBehavior而另一个有BottomSheetBehavior并且扮演BottomSheet角色,问题出在我身上时拖动BottomSheet,第一个NestedScrollView滚动:

enter image description here

我的期望:
 当我滚动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>

1 个答案:

答案 0 :(得分:6)

更新了更简单的解决方案。

您的问题的解决方案可分为两个部分:

  1. 如何在不滚动appbar的情况下抬起底部工作表?
  2. 如何提升底部纸张。
  3. 要在不影响appbar的情况下提升底部工作表,我们需要检测底部工作表何时负责滚动并让appbar拒绝嵌套滚动,以便它不会接收后续嵌套滚动事件。这是通过AppBarLayout.Behavior MyAppBarBehavior方法完成的。 (请参阅下面AppBarLayout.Behavior的代码。)

    我们现在可以像一个独立的滑动面板一样向上拖动底部纸张。

    onStartNestedScroll

    现在我们已经将底部纸张拖了起来,我们可以将它拖回来吗?是的,不。如果底部工作表滚动到其内容的顶部,那么如果我们触摸底部工作表下面的,我们可以向下拖动底部工作表。如果我们触摸appbar上的底部纸张(当然,它位于底部纸张后面),那么我们就无法将底部纸张向下拖动。未经我们修改,此问题存在于基础代码中。我认为底页覆盖appbar是不寻常的。

    为了演示此通知,在此视频中,当拖动底部工作表时,appbar会在底部工作表后面打开。

    enter image description here

    要更改此行为,我们会覆盖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}}

    以下是最终结果:

    enter image description here

    可能还有其他方法可以实现这一目标。我可能会使用现有的滑动面板库,例如onInterceptTouchEvent,而不是将底部工作表放在嵌套的滚动环境中,然后我们必须撤消环境的影响。