AppBarLayout阻止RecyclerView在BottomSheet中滚动

问题描述

我做了一个简单的布局,其中有一个AppBarLayout(不会滚动),中间的一些内容以及一个BottomSheet。该BottomSheet实际上是带有BottomSheetBehavior的LinearLayout,并且内部具有RecyclerView。

展开时,此BottomSheet将RecyclerView放置在AppBarLayout的顶部。问题在于,当用户尝试滚动此RecyclerView时,下面的AppBarLayout会窃取滚动。

我要保留布局代码,但是我将整个example project上载了带有GIF的GitHub进行了说明。

布局

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.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/coordinator_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/app_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:liftOnScroll="false">

        <com.google.android.material.appbar.MaterialToolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            app:title="@string/app_name" />

        <androidx.appcompat.widget.AppCompatTextView
            android:layout_width="match_parent"
            android:layout_height="56dp"
            android:background="?colorSurface"
            android:gravity="center_vertical"
            android:padding="16dp"
            android:text="Subtitle"
            android:textAppearance="?textAppearanceSubtitle1" />

        <androidx.appcompat.widget.AppCompatTextView
            android:layout_width="match_parent"
            android:layout_height="56dp"
            android:background="?colorSurface"
            android:gravity="center_vertical"
            android:padding="16dp"
            android:text="Subsubtitle"
            android:textAppearance="?textAppearanceBody2" />

    </com.google.android.material.appbar.AppBarLayout>

    <androidx.core.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingBottom="56dp"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <androidx.appcompat.widget.AppCompatTextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="16dp"
            android:text="@string/lorem_ipsum"
            android:textAppearance="?textAppearanceBody1" />

    </androidx.core.widget.NestedScrollView>

    <LinearLayout
        android:id="@+id/bottom_sheet_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="bottom"
        android:background="#FFF"
        android:elevation="5dp"
        android:orientation="vertical"
        app:behavior_hideable="false"
        app:behavior_peekHeight="64dp"
        app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">

        <androidx.appcompat.widget.AppCompatTextView
            android:id="@+id/bottom_sheet_header"
            android:layout_width="match_parent"
            android:layout_height="64dp"
            android:gravity="center_vertical"
            android:padding="16dp"
            android:text="Fruits"
            android:textAppearance="?textAppearanceHeadline6" />

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recycler_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />

    </LinearLayout>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

我尝试过:

  • 在各个位置放置nestedScrollingEnabled属性,但是没有用,并且这种行为在旧的API(例如JellyBean)中出现;
  • 在看到此内容的原始项目中,我编写了一个自定义AppBarLayout行为,以忽略目标视图是否为BottomSheet的RecyclerView,但也没有起作用;
  • 当BottomSheet展开且足够有趣时,设置整个AppBarLayout GONE,AppBarLayout的行为就像我设置为INVISIBLE一样(如果以编程方式设置为GONE,则它的行为就像不可见,如果设置了在充气之前,它的行为符合预期)。

由于项目规范,我避免使用Fragment创建此BottomSheet。

解决方法

我所做的解决方法是将CoordinatorLayout拆分为2,其中一个包含AppBarLayout和NestedScrollView,另一个包含BottomSheet(LinearLayout)。

以问题的布局为例的层次结构最终如下:

<FrameLayout>
    <CoordinatorLayout>
        <AppBarLayout>
            <MaterialToolbar/>
            <AppCompatTextView/>
            <AppCompatTextView/>
        </AppBarLayout>
        <NestedScrollView>
            <AppCompatTextView/>
        </NestedScrollView>
    </CoordinatorLayout>

    <CoordinatorLayout>
        <LinearLayout>
            <AppCompatTextView/>
            <RecyclerView/>
        </LinearLayout>
    </CoordinatorLayout>
</FrameLayout>

在我看来,这是可行的,因为我的BottomSheet不需要与其他视图协调任何行为。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...