滚动不适用于CoordinatorLayout +视差图像+ BottomSheetLayout
介绍
我有一个活动,使用CoordinatorLayout
, AppBarLayout
和CollapsingToolbarLayout
实现一个常见的模式与视差标题图像和滚动内容。 我的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
滚动整个屏幕。
问题
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
滚动。 从内容NestedScrollView
和Toolbar
滚动按预期工作。
题
我怎样才能管理滚动工作从视差View
以及(在第一个GIF动画相同的方式)? 看起来BottomSheetBehavior
拦截触摸事件并阻止AppBarLayout
( AppBarLayoutBehavior
)处理滚动。 但奇怪的是,从Toolbar
滚动工作,视差View
和Toolbar
是AppBarLayout
。
我认为你应该使用NestedScrollView
与BottomSheetBehavior
,取代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
扩展 -
覆盖
onStartNestedScroll
和onNestedFling
-
创建一个像
scrollDenial
这样的标志,并将其添加到下面的两个方法中,然后调用super(scrollDenial && super.onStartNestedScroll …) -
现在,您需要更新每个onStartNestedScroll上的拒绝条件。 我做了这样的事情:
https://gist.github.com/recoverrelax/8dd37b54910d70b5cd6a130a070c51e9
PS。 我很抱歉,但这是Kotlin:p不应该很难理解tho。 它解决了bottomSheet问题。