滚动不适用于CoordinatorLayout + parallax image + BottomSheetLayout

问题描述 投票:22回答:6

介绍

我有一个活动,它使用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),以帮助开发人员实施Bottom sheets。我的带有Bottom工作表的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的孩子。

android android-coordinatorlayout android-collapsingtoolbarlayout android-appbarlayout bottom-sheet
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>


0
投票

我认为你应该使用NestedScrollViewBottomSheetBehavior,替换打击作为bootemSheet!

<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

希望有所帮助!!


0
投票

这似乎是BottomSheetBehavior代码中的一个错误,因为如果你试图调试CoordinatorLayout的代码你会看到当你触摸你的视差View它将被确定为BottomSheetBehavior而不是HeaderBehavior的布局。

所以我发现的快速修复是设置OnTouchListener,它总是返回true给你的视差视图:

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
投票

可以通过在FrameLayout中的CoordinatorLayout外移动NestedScrollView(或在我的情况下包含NestedScrollView的片段)并在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对任何触摸事件做出反应(和拦截)的唯一方法。 #JustGoogleThings


0
投票

我想出了自己的答案:

  • app:layout_behavior="...AppBarLayoutCustomBehavior"添加到你的appBarLayout
  • 创建该类并从AppBarLayout.Behavior扩展
  • 覆盖onStartNestedScrollonNestedFling
  • 创建一个像scrollDenial的标志,并将其添加到下面的两个方法,然后调用super(scrollDenial && super.onStartNestedScroll ...)
  • 现在,您需要在每个onStartNestedScroll上更新拒绝条件。我做了这样的事情: https://gist.github.com/recoverrelax/8dd37b54910d70b5cd6a130a070c51e9

PS。对不起,这是Kotlin:p不应该很难理解。它解决了bottomSheet问题。

© www.soinside.com 2019 - 2024. All rights reserved.