将 BottomSheetBehavior 与内部 CoordinatorLayout 一起使用

Using BottomSheetBehavior with a inner CoordinatorLayout

设计支持库 v. 23.2 引入了 BottomSheetBehavior,它允许协调器的子项充当底部 sheets(可从屏幕底部拖动​​的视图)。

我想要做的是作为底部sheet视图,以下视图(典型的协调器+折叠的东西):

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

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

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

</CoordinatorLayout>

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

我很确定这可以通过子类化 CoordinatorLayout 来处理,或者通过子类化 BottomSheetBehavior 更好。你有什么提示吗?

一些想法

问题

不用说,我现在无法完成这项工作。当条件满足时,我无法捕获事件,而在其他情况下则无法捕获。在下图中,您可以看到标准 CoordinatorLayout 会发生什么:

我已经设置了一个 sample project on github 来显示这些问题。

需要说明的是,期望的行为是:

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

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"/>

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

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

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

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

尽量不要将 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>

我刚刚按照你提出上述问题的方式提出了可能需要更多的解决方案 explanation.Please 按照你的示例代码并将额外的部分集成到你的 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

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

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

为防止这种情况发生,您需要创建自定义 AppBarLayout.Behavior,因为只有当您在拖动的同时向上滚动时,AppBarLayout.behavior 才会获得滚动动作。我们需要检测它是否在 STATE_DRAGGING 中并且只是 return 以避免 hiding/collapsing 工具栏过早出现。

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 人,但努力工作会有所回报有时理解代码,找到正确的 callback/override 函数来实现。

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

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

compile 'com.otaliastudios:bottomsheetcoordinatorlayout:1.0.0’

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

我已经用了很久了,应该不会有滚动问题,支持在ABL上拖动等等