使用带有内部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并设置屏幕的偏移量。