滚动不适用于CoordinatorLayout +视差图像+ BottomSheetLayout

介绍

我有一个活动,使用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

问题

Google推出了一个BottomSheetBehavior类(Android设计支持库23.2 )来帮助开发者实现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> 

结果如下所示:

在这里输入图像描述

正如你所看到的,现在我无法滚动,如果我开始从视差View滚动。 从内容NestedScrollViewToolbar滚动按预期工作。

我怎样才能管理滚动工作从视差View以及(在第一个GIF动画相同的方式)? 看起来BottomSheetBehavior拦截触摸事件并阻止AppBarLayoutAppBarLayoutBehavior )处理滚动。 但奇怪的是,从Toolbar滚动工作,视差ViewToolbarAppBarLayout

我认为你应该使用NestedScrollViewBottomSheetBehavior ,取代blow作为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

希望帮助!

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

所以我找到的快速解决方案是设置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"为视图。

希望它有帮助!

尝试这个

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

将高度400dp更改为wrap_content

希望适合你

我正在复制粘贴我正在使用的XML。 它的工作方式三星Galaxy S3,华为Mate 8和摩托,我还没有尝试过仿真器(我删除了所有的业务的东西,只是把虚构的小部件)。

 <?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> 

这个问题可以通过在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

我想出了自己的答案:

  • app:layout_behavior="...AppBarLayoutCustomBehavior"到您的appBarLayout

  • 创建该类并从AppBarLayout.Behavior扩展

  • 覆盖onStartNestedScrollonNestedFling

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

  • 现在,您需要更新每个onStartNestedScroll上的拒绝条件。 我做了这样的事情:

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

PS。 我很抱歉,但这是Kotlin:p不应该很难理解tho。 它解决了bottomSheet问题。

Interesting Posts