CoordinatorLayout + 视差图像 + BottomSheetLayout,滚动不起作用

23

介绍

我有一个活动,它使用 CoordinatorLayoutAppBarLayoutCollapsingToolbarLayout 实现了带视差头部图像和滚动内容的常见模式。我的 xml 布局如下:

<android.support.design.widget.CoordinatorLayout
    android:fitsSystemWindows="true"
    android:layout_height="match_parent"
    android:layout_width="match_parent">

    <android.support.design.widget.AppBarLayout
        android:fitsSystemWindows="true"
        android:id="@+id/appbar"
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.design.widget.CollapsingToolbarLayout
            android:fitsSystemWindows="true"
            android:layout_height="wrap_content"
            android:layout_width="match_parent"
            app:contentScrim="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">

            <TextView
                android:background="@color/colorAccent"
                android:gravity="center"
                android:layout_height="250dp"
                android:layout_width="match_parent"
                android:text="ParallaxImage"
                app:layout_collapseMode="parallax"/>

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_height="?attr/actionBarSize"
                android:layout_width="match_parent"
                app:layout_collapseMode="pin"
                app:popupTheme="@style/AppTheme.PopupOverlay"/>

        </android.support.design.widget.CollapsingToolbarLayout>
    </android.support.design.widget.AppBarLayout>

    <android.support.v4.widget.NestedScrollView
        android:id="@+id/content"
        android:layout_height="match_parent"
        android:layout_width="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <TextView
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/text_margin"
            android:layout_width="wrap_content"
            android:text="@string/large_text"/>
    </android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>

正如您在下面的gif动画中所看到的,一切都正常工作。您可以从内容NestedScrollView以及从Toolbar或视差View滚动整个屏幕。

AppBarLayout + NestedScrollView

问题

谷歌推出了一个BottomSheetBehavior类(Android设计支持库23.2),以帮助开发人员实现底部工作表。我的包含底部工作表的xml布局如下:

<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fitsSystemWindows="true"
        android:theme="@style/AppTheme.AppBarOverlay">
        <!-- ommited -->
    </android.support.design.widget.AppBarLayout>

    <android.support.v4.widget.NestedScrollView
        android:id="@+id/content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">
        <!-- ommited -->
    </android.support.v4.widget.NestedScrollView>

    <LinearLayout
        android:id="@+id/bottomSheet"
        android:layout_width="match_parent"
        android:layout_height="400dp"
        android:background="@android:color/holo_blue_bright"
        android:orientation="vertical"
        app:behavior_peekHeight="?attr/actionBarSize"
        app:layout_behavior="android.support.design.widget.BottomSheetBehavior">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:gravity="center_vertical"
            android:paddingLeft="16dp"
            android:paddingRight="16dp"
            android:text="BottomSheetLayout"
            android:textColor="@android:color/white"/>

        <android.support.v4.widget.NestedScrollView
            android:id="@+id/bottomSheetContent"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:scrollbars="vertical">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="400dp"
                android:background="@android:color/holo_green_dark"
                android:padding="16dp"
                android:text="@string/large_text"
                android:textColor="@android:color/white"/>

        </android.support.v4.widget.NestedScrollView>
    </LinearLayout>

</android.support.design.widget.CoordinatorLayout>

结果如下所示:

enter image description here

如您所见,现在我无法滚动,如果我从视差View开始滚动的话。从内容NestedScrollViewToolbar开始滚动则按预期工作。
问题
如何才能使视差View也能像第一个gif动画一样正常工作?似乎BottomSheetBehavior拦截了触摸事件并阻止了AppBarLayout (AppBarLayoutBehavior)处理滚动。但奇怪的是,从Toolbar开始滚动可以工作,而且视差ViewToolbar都是AppBarLayout的子项。

你修复了你的 bug 吗?我也遇到了同样的问题:https://dev59.com/Zqrka4cB1Zd3GeqPlO3X - yozhik
6个回答

1
我正在复制粘贴使用的XML。顺便说一下,它在三星Galaxy S3、华为Mate 8和Moto上运行良好,我还没有在模拟器上尝试过(我删除了所有业务相关内容,只放了虚拟小部件)。
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/coordinatorlayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">

<android.support.design.widget.AppBarLayout
    android:id="@+id/appbarlayout"
    android:layout_width="match_parent"
    android:layout_height="256dp"
    android:theme="@style/AppTheme.AppBarOverlay"
    android:fitsSystemWindows="true">

    <android.support.design.widget.CollapsingToolbarLayout
        android:id="@+id/collapsing_toolbar"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_scrollFlags="scroll|exitUntilCollapsed"
        android:fitsSystemWindows="true"
        app:contentScrim="?attr/colorPrimary"
        app:expandedTitleMarginStart="48dp"
        app:expandedTitleMarginEnd="64dp">

        <ImageView
            android:id="@+id/backdrop"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scaleType="centerCrop"
            android:fitsSystemWindows="true"
            app:layout_collapseMode="parallax"/>


        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            app:popupTheme="@style/AppTheme.PopupOverlay"
            app:layout_collapseMode="pin"/>

    </android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>



<android.support.v4.widget.NestedScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:paddingBottom="16dp">

        <android.support.v7.widget.CardView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="16dp">

            <LinearLayout
                style="@style/Widget.CardContent"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo." />

            </LinearLayout>

        </android.support.v7.widget.CardView>

        <android.support.v7.widget.CardView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="16dp"
            android:layout_marginLeft="16dp"
            android:layout_marginRight="16dp">

            <LinearLayout
                style="@style/Widget.CardContent"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="TITLE"
                android:textAppearance="@style/TextAppearance.AppCompat.Title" />

                    <TextView
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:text="text 1" />

                    <TextView
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:text="text 2" />

                    <TextView
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:text="text 3" />

                    <TextView
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:text="text 4" />

                    <TextView
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:text="text 5" />

                </LinearLayout>

            </android.support.v7.widget.CardView>
        </LinearLayout>
    </android.support.v4.widget.NestedScrollView>


<android.support.v4.widget.NestedScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    app:behavior_peekHeight="100dp"
    android:fitsSystemWindows="true"
    app:layout_behavior="android.support.design.widget.BottomSheetBehavior">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:paddingBottom="16dp"
        android:background="@android:color/white"
        android:padding="15dp">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="BOOTOMSHEET TITLE"
            android:textAppearance="@style/TextAppearance.AppCompat.Title" />

        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Button1"/>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="text 2"
            android:layout_margin="10dp"/>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="text 3"
            android:layout_margin="10dp"/>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="text 4"
            android:layout_margin="10dp"/>


        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="320dp"
            android:background="@color/colorAccent">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:text="Your remaining content here"
                android:textColor="@android:color/white" />

        </FrameLayout>
    </LinearLayout>
</android.support.v4.widget.NestedScrollView>


如果您想要一个gif演示它的工作原理,请告诉我您是如何做到的,我会更新答案并提供给您 :) - MiguelHincapieC
能否分享更多关于您代码的信息?例如gif、设备等。因为我曾在许多模拟器和真实设备上进行过测试,而且正常运行。 - MiguelHincapieC

0

我想出了自己的答案:

  • app:layout_behavior="...AppBarLayoutCustomBehavior" 添加到你的 appBarLayout 中。

  • 创建一个类并继承自 AppBarLayout.Behavior

  • 重写 onStartNestedScrollonNestedFling

  • 创建一个名为 scrollDenial 的标志,并将其添加到下面的两个方法中,然后调用 super (scrollDenial && super.onStartNestedScroll...)

  • 现在,你需要在每次 onStartNestedScroll 中更新你的拒绝条件。我做了类似于这样的事情:

    https://gist.github.com/recoverrelax/8dd37b54910d70b5cd6a130a070c51e9

附:抱歉,但这是 Kotlin :p 不过应该不难理解。它解决了 bottomSheet 问题。


0
问题可以通过将NestedScrollView(或包含NestedScrollView的片段,在我的情况下)移出CoordinatorLayout并将其放置在FrameLayout中,并在原来的NestedScrollView位置放置一个虚拟视图来解决,如下所示:
<FrameLayout>
    <CoordinatorLayout>
        <AppBarLayout>
            ...
        </AppBarLayout>
        <View
            android:id="@+id/bottomSheet"
            app:layout_behavior="android.support.design.widget.BottomSheetBehavior" />
    </CoordinatorLayout>
    <NestedScrollView
        android:id="@+id/bottomSheetContent">
        ...
    </NestedScrollView>
</FrameLayout>

最后,在虚拟视图中添加一个BottomSheetCallback,在滑动时将实际内容视图进行翻译:
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
    bottomSheetContent.setTranslationY((1f - slideOffset) * bottomSheetContent.getHeight());
}

看起来,这是防止CoordinatorLayout对任何触摸事件做出反应(和拦截)的唯一方法。#只有谷歌知道


0

这似乎是BottomSheetBehavior代码中的一个错误,因为如果您尝试调试CoordinatorLayout的代码,您会发现当您触摸视差View时,它将被确定为具有BottomSheetBehavior而不是HeaderBehavior的布局。

所以我找到的快速解决方法是为您的视差视图设置始终返回true的OnTouchListener

View parallaxView = findViewById(R.id.parallax_view);
parallaxView.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        return true;
    }
});

当然,不要忘记将android:id="@+id/parallax_view"设置给具有视差折叠模式的视图。
希望对你有所帮助!

0

试试这个

 <LinearLayout
        android:id="@+id/bottomSheet"
        android:layout_width="match_parent"
        android:layout_height="400dp">

将高度从400dp更改为wrap_content
希望对您有所帮助。

0

我认为你应该使用NestedScrollViewBottomSheetBehavior,将其替换为底部表单!

<android.support.v4.widget.NestedScrollView
    android:id="@+id/bottomSheet"
    android:layout_width="match_parent"
    android:layout_height="400dp"
    android:background="@android:color/holo_blue_bright"
    android:orientation="vertical"
    app:behavior_peekHeight="?attr/actionBarSize"
    app:layout_behavior="android.support.design.widget.BottomSheetBehavior">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:gravity="center_vertical"
            android:paddingLeft="16dp"
            android:paddingRight="16dp"
            android:text="BottomSheetLayout"
            android:textColor="@android:color/white"/>

        <ScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="400dp"
                android:background="@android:color/holo_green_dark"
                android:padding="16dp"
                android:text="@string/large_text"
                android:textColor="@android:color/white"/>
        </ScrollView>
    </LinearLayout>

</android.support.v4.widget.NestedScrollView>

NestedScrollView 可以知道如何与工具栏嵌套,而不是 LinearLayout

希望能够帮到你!


这与我无关,也没有帮助到我...但还是谢谢。 - traninho

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接