如何使底页(BottomSheetBehavior)可扩展到任意位置?

Ale*_*kov 7 android google-maps bottom-sheet

我有底页,我想改变它的行为,所以它会像在谷歌地图应用程序的主屏幕上一样工作,你可以将它扩展到任何位置,并留在那里,它不会自动粘在底部或顶端.这是我的底部布局:

<android.support.design.widget.CoordinatorLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.google.android.gms.maps.MapView
        android:id="@+id/map"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <View
        android:id="@+id/shadow"
        android:layout_width="match_parent"
        android:layout_height="16dp"
        android:background="@drawable/shape_gradient_top_shadow"
        app:layout_anchor="@+id/map_bottom_sheet" />


    <LinearLayout
        android:id="@+id/map_bottom_sheet"
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:fillViewport="false"
        android:orientation="vertical"
        app:behavior_peekHeight="50dp"
        android:background="@color/lightGray"
        app:layout_behavior="android.support.design.widget.BottomSheetBehavior">

        <include layout="@layout/bottom_sheet_top_buttons"/>
        <android.support.v4.widget.NestedScrollView
            android:id="@+id/bottom_sheet_content_fragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@color/lightGray"/>

    </LinearLayout>

</android.support.design.widget.CoordinatorLayout>
Run Code Online (Sandbox Code Playgroud)

我本质上需要的是在拖动结束时消除强制STATE_EXPANDEDSTATE_COLLAPSED状态.

这是我尝试实现的目标的直观解释:


如您所见,底部纸张不会自动锚定到顶部或底部,而是保持在它留下的任何位置.

Mar*_*ius 5

复制代码android.support.design.widget.BottomSheetBehavior以制作您自己的自定义行为.然后修改onViewReleased()拖动结束后负责纸张移动的方法.除了现有状态之外,您还必须引入一种新状态 - 状态有助于恢复位置并让其他人知道您的工作表目前处于哪种状态getState().

@Override
public void onViewReleased(View releasedChild, float xVel, float yVel) {
    int top;
    @State int targetState;

    // Use the position where the drag ended as new top
    top = releasedChild.getTop();

    // You have to manage the states here, too (introduce a new one)
    targetState = STATE_ANCHORED;

    if (mViewDragHelper.settleCapturedViewAt(releasedChild.getLeft(), top)) {
        setStateInternal(STATE_SETTLING);
        ViewCompat.postOnAnimation(releasedChild, new SettleRunnable(releasedChild, targetState));

    } else {
        setStateInternal(targetState);
    }
}
Run Code Online (Sandbox Code Playgroud)


Alo*_*lok 2

你好,亚历克斯,你可以尝试这个代码来实现类似的预期行为,它没有那么优化,但它将帮助你理解这个概念。

     final DisplayMetrics metrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(metrics);
 bottomSheetBehavior.setPeekHeight(200);
// set callback for changes
        bottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
            @Override
            public void onStateChanged(@NonNull View bottomSheet, int newState) {

                Log.d(TAG, "onStateChanged: " + bottomSheet.getY() + "::" + bottomSheet.getMeasuredHeight() + " :: " + bottomSheet.getTop());

            }

            @Override
            public void onSlide(@NonNull View bottomSheet, float slideOffset) {


                ViewGroup.LayoutParams params = bottomSheet.getLayoutParams();
                params.height = Math.max(0, metrics.heightPixels - (int) bottomSheet.getTop());
                bottomSheet.setLayoutParams(params);




            }
        });
Run Code Online (Sandbox Code Playgroud)