将BottomSheetBehavior与内部CoordinatorLayout

时间:2016-03-25 23:50:33

标签: android android-support-library ontouchlistener ontouchevent android-support-design

设计支持库v. 23.2引入了BottomSheetBehavior,它允许协调员的子节点作为底部工作表(可从屏幕底部拖动​​的视图)。

我想做的是将作为底层视图,以下视图(典型的协调员+折叠内容):

<CoordinatorLayout
    app:layout_behavior=“@string/bottom_sheet_behavior”>

   <AppBarLayout>
        <CollapsingToolbarLayout>
           <ImageView />
        </CollapsingToolbarLayout>
    </AppBarLayout>

    <NestedScrollView>
        <LinearLayout>
            < Content ... />
        </LinearLayout>
    </NestedScrollView>

</CoordinatorLayout>

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

我很确定这可以通过子类化CoordinatorLayout来处理,甚至可以通过子类化BottomSheetBehavior来实现。你有什么提示吗?

一些想法

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

    • AppBarLayout偏移量为&gt;时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。

enter image description here

我设置了显示这些问题的sample project on github

为了清楚起见,期望的行为是:

  • 更正工作表内的appbars /滚动视图的行为;

  • 展开工作表时,它可以向下滚动时折叠,但仅当内部应用栏完全展开时 。现在它崩溃而不考虑appbar状态,只有当你拖动appbar时才会崩溃;

  • 折叠工作表时,向上滚动手势会将其展开(对内部应用栏没有影响)。

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

enter image description here

6 个答案:

答案 0 :(得分:5)

我终于发布了我的实现。找到它on Github或直接从jcenter:

compile 'com.otaliastudios:bottomsheetcoordinatorlayout:1.0.0’

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

我已经使用了很长时间了,它不应该有滚动问题,支持拖动ABL等。

答案 1 :(得分:1)

我刚刚按照您提出上述问题的方式提出并提出了可能需要更多解释的解决方案。请按照示例代码将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>

注意:对我有用的解决方案已在您问题的最后评论中解释

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

答案 2 :(得分:0)

如果第一个孩子是nestedscroll,则会出现其他一些问题。这个解决方案解决了我的问题,我希望也能解决你的问题。

<CoordinatorLayout
    app:layout_behavior=“@string/bottom_sheet_behavior”>

   <AppBarLayout>
        <CollapsingToolbarLayout>
           <ImageView />
        </CollapsingToolbarLayout>
    </AppBarLayout>
</LinearLayout>
    <NestedScrollView>
        <LinearLayout>
            < Content ... />
        </LinearLayout>
    </NestedScrollView>
</LinearLayout>
</CoordinatorLayout>

答案 3 :(得分:0)

尽量不要将NestedScrollViewLinearLayout一起使用,它也会在我的应用中造成问题。只需使用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>

答案 4 :(得分:0)

我已经关注了laenger关于这个问题的初始github测试项目,我很高兴为您分享他的一些问题的解决方案,因为我在我的应用程序中也需要这种行为。

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

要防止这种情况发生,您需要创建自定义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);
    }
}

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

❌工具栏无法通过拖动折叠

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

我实际上并不是一个优秀的用户界/动画人,但有时候,努力工作无需理解代码,找到正确的回调/覆盖功能来实现。

将此设置为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">

答案 5 :(得分:-4)

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并设置screen的偏移量。