使用带有内部CoordinatorLayout的BottomSheetBehavior

devise支持库BottomSheetBehavior介绍了BottomSheetBehavior ,它允许一个协调器的孩子充当最底层(从屏幕底部可以拖动的视图)。

我想要做的是, 作为底部视图 ,有以下视图(典型的协调员+崩溃的东西):

 <CoordinatorLayout app:layout_behavior=“@string/bottom_sheet_behavior”> <AppBarLayout> <CollapsingToolbarLayout> <ImageView /> </CollapsingToolbarLayout> </AppBarLayout> <NestedScrollView> <LinearLayout> < Content ... /> </LinearLayout> </NestedScrollView> </CoordinatorLayout> 

不幸的是,底部视图应该实现嵌套滚动,否则他们不会得到滚动事件。 如果您尝试使用主要活动,然后将此视图作为底部表单加载,则会看到滚动事件仅作用于“纸张”上,出现了一些奇怪的行为,您可以看到是否继续阅读。

我很确定这可以通过inheritanceCoordinatorLayout来处理,或者通过BottomSheetBehavior 。 你有什么提示吗?

一些想法

  • 应该使用requestDisallowInterceptTouchEvent()来在某些情况下从父requestDisallowInterceptTouchEvent()中窃取事件:

    • AppBarLayout偏移量> 0时
    • AppBarLayout偏移量是== 0,但我们正在滚动(想一下,你会看到)
  • 第一个条件可以通过设置OnOffsetChanged到内部的应用程序栏获得;

  • 第二个需要一些事件处理,例如:

     switch (MotionEventCompat.getActionMasked(event)) { case MotionEvent.ACTION_DOWN: startY = event.getY(); lastY = startY; userIsScrollingUp = false; break; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: userIsScrollingUp = false; break; case MotionEvent.ACTION_MOVE: lastY = event.getY(); float yDeltaTotal = startY - lastY; if (yDeltaTotal > touchSlop) { // Moving the finger up. userIsScrollingUp = true; } break; } 

问题

不用说,我现在不能做这个工作。 当条件得到满足时,我无法把握事件的发生,而在其他情况下不能抓住事件。 在下面的图片中,您可以看到标准CoordinatorLayout会发生什么情况:

  • 如果您在应用程序栏上向下滚动,表将被解散,但如果向下滚动嵌套的内容,则表不会被解除。 似乎嵌套的滚动事件不会传播到协调器的行为;

  • 内部appbar也有问题:嵌套的滚动内容在折叠时不遵循appbar。

在这里输入图像说明

我已经在github上设置了一个示例项目来显示这些问题。

要明确,理想的行为是:

  • 修正工作表内的appbars / scroll视图的行为;

  • 当表单被展开时,它可以在向下滚动时折叠,但只有在内部的appbar也完全展开的情况下 。 现在它确实崩溃,不考虑appbar状态,只有当你拖动appbar;

  • 表单折叠后,向上滚动手势将展开它(对内部应用程序栏没有影响)。

来自联系人应用程序的示例(可能不使用BottomSheetBehavior,但这是我想要的):

在这里输入图像说明

我终于发布了我的实现。 在Github上或直接从jcenter 上find它:

 compile 'com.otaliastudios:bottomsheetcoordinatorlayout:1.0.0' 

您所要做的就是使用BottomSheetCoordinatorLayout作为底部视图的根视图。 它会自动夸大自己的工作行为,所以不要担心。

我一直在使用这个很长一段时间,它不应该有卷动问题,支持拖动ABL等。

我刚刚按照你问上述问题的方式,并提出可能需要更多解释的解决scheme。请按照您的示例代码,并将额外的部分集成到您的XML中,使其行为像BottomSheeet行为

 <CoordinatorLayout> <AppBarLayout> <Toolbar app:layout_collapseMode="pin"> </Toolbar> </AppBarLayout> <NestedScrollView app:layout_behavior=“@string/bottom_sheet_behavior” > <include layout="@layout/items" /> </NestedScrollView> <!-- Bottom Sheet --> <BottomSheetCoordinatorLayout> <AppBarLayout <CollapsingToolbarLayout"> <ImageView /> <Toolbar /> </CollapsingToolbarLayout> </AppBarLayout> <NestedScrollView"> <include layout="@layout/items" /> </NestedScrollView> </BottomSheetCoordinatorLayout> </CoordinatorLayout> 

注意:为我工作的解决scheme已经在你的问题的最后评论中解释过了

更好的解释: https //github.com/laenger/BottomSheetCoordinatorLayout

如果第一个孩子nestedscroll这将发生一些其他问题。 这个解决scheme是解决我的问题,我希望也能解决你的问题。

 <CoordinatorLayout app:layout_behavior=“@string/bottom_sheet_behavior”> <AppBarLayout> <CollapsingToolbarLayout> <ImageView /> </CollapsingToolbarLayout> </AppBarLayout> </LinearLayout> <NestedScrollView> <LinearLayout> < Content ... /> </LinearLayout> </NestedScrollView> </LinearLayout> </CoordinatorLayout> 

尽量不要在LinearLayout使用NestedScrollView ,它也会导致我的应用程序出现问题。 只需要使用LinearLayout ,对我来说工作正常。

尝试以下操作:

 <CoordinatorLayout app:layout_behavior=“@string/bottom_sheet_behavior”> <AppBarLayout> <CollapsingToolbarLayout> <ImageView /> </CollapsingToolbarLayout> </AppBarLayout> <LinearLayout> <!--don't forget to addd this line--> app:layout_behavior="@string/appbar_scrolling_view_behavior"> < Content ... /> </LinearLayout> 

我已经关注了langer的初始githubtesting项目关于这个问题,我很高兴分享你一些他的问题的解决scheme,因为我需要我的应用程序中的这种行为。

这是他的问题的解决scheme:❌工具栏有时会过早崩溃

为了防止这种情况,您需要创build自定义的AppBarLayout.Behavior ,因为当您向上滚动时,仍然拖动AppBarLayout.behavior获取滚动动作。 我们需要检测它是否在STATE_DRAGGING中,然后返回以避免过早地隐藏/折叠工具栏。

 public class CustomAppBarLayoutBehavior extends AppBarLayout.Behavior { private CoordinatorLayoutBottomSheetBehavior behavior; public CustomAppBarLayoutBehavior() { } public CustomAppBarLayoutBehavior(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean onStartNestedScroll(CoordinatorLayout parent, AppBarLayout child, View directTargetChild, View target, int nestedScrollAxes) { behavior = CoordinatorLayoutBottomSheetBehavior.from(parent); return super.onStartNestedScroll(parent, child, directTargetChild, target, nestedScrollAxes); } @Override public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, int dx, int dy, int[] consumed) { if(behavior.getState() == CoordinatorLayoutBottomSheetBehavior.STATE_DRAGGING){ return; }else { super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed); } } @Override public void setDragCallback(@Nullable DragCallback callback) { super.setDragCallback(callback); } } 

这可能是我们如何解决其他问题的良好开端:

❌工具栏不能通过拖动折叠

❌主协调员布局消耗一些滚动

我实际上并不是一个好的UI /animation人,但是硬性工作有时会理解代码,find正确的callback/覆盖function来实现。

将其设置为appbarlayout的行为

 <android.support.design.widget.AppBarLayout android:id="@+id/bottom_sheet_appbar" style="@style/BottomSheetAppBarStyle" android:layout_width="match_parent" android:layout_height="wrap_content" app:layout_behavior="your.package.CustomAppBarLayoutBehavior"> 

appbar布局的全屏布局如下:

 <android.support.design.widget.AppBarLayout android:id="@+id/appbar" android:layout_width="match_parent" android:layout_height="@dimen/detail_backdrop_height" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" 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/ThemeOverlay.AppCompat.Light" 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:paddingTop="24dp"> <android.support.v7.widget.CardView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="@dimen/card_margin"> <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="Info" android:textAppearance="@style/TextAppearance.AppCompat.Title" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/cheese_ipsum" /> </LinearLayout> </android.support.v7.widget.CardView> <android.support.v7.widget.CardView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="@dimen/card_margin" android:layout_marginLeft="@dimen/card_margin" android:layout_marginRight="@dimen/card_margin"> <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="Friends" android:textAppearance="@style/TextAppearance.AppCompat.Title" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/cheese_ipsum" /> </LinearLayout> </android.support.v7.widget.CardView> <android.support.v7.widget.CardView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="@dimen/card_margin" android:layout_marginLeft="@dimen/card_margin" android:layout_marginRight="@dimen/card_margin"> <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="Related" android:textAppearance="@style/TextAppearance.AppCompat.Title" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/cheese_ipsum" /> </LinearLayout> </android.support.v7.widget.CardView> </LinearLayout> </android.support.v4.widget.NestedScrollView> <android.support.design.widget.FloatingActionButton android:layout_height="wrap_content" android:layout_width="wrap_content" app:layout_anchor="@id/appbar" app:layout_anchorGravity="bottom|right|end" android:src="@drawable/ic_discuss" android:layout_margin="@dimen/fab_margin" android:clickable="true"/> 

之后你应该在你的类中实现AppBarLayout.OnOffsetChangedListener并设置屏幕的偏移量。