我如何为我的 BottomSheet 设置半展开状态

How i can set Half Expanded state for my BottomSheet

我的布局有底部 sheet。

<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/coordinator_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <com.google.android.material.appbar.CollapsingToolbarLayout
            android:id="@+id/collapsing_toolbar"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:contentScrim="@color/colorPrimary"
            app:layout_scrollFlags="scroll|exitUntilCollapsed" />
    </com.google.android.material.appbar.AppBarLayout>


    <include layout="@layout/content_main_weather_map" />

    <include layout="@layout/bottom_sheet" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

底部sheet布局

 <?xml version="1.0" encoding="utf-8"?>
    <androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/bottom_sheet"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/white"
        android:clipToPadding="true"
        app:behavior_peekHeight="80dp"
        app:layout_behavior="@string/bottom_sheet_behavior">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/weather_recycler"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="8dp"
                tools:listitem="@layout/item_weather" />

        </LinearLayout>


    </androidx.core.widget.NestedScrollView>

我的底部sheet打开前半部分,重新​​拖动后打开全屏,这对我来说是必要的。 google 地图应用程序是如何完成的。但是我不知道该怎么做。

只需将 BottomSheetBehaivor 状态设置为 BottomSheetBehavior.STATE_HALF_EXPANDED。 此外,如果您需要在完全展开后让用户再次回到半展开模式,您需要将 peek 高度设置为 window 高度的一半。

val bottomSheetBehavior = BottomSheetBehavior.from<NestedScrollView>(bottom_sheet)
val metrics = resources.displayMetrics
bottomSheetBehavior.peekHeight = metrics.heightPixels / 2
bottomSheetBehavior.state = BottomSheetBehavior.STATE_HALF_EXPANDED

虽然这个问题已经得到解答,但只是得到了另一种实现此行为的方法,所以分享给其他人。

创建一个全局变量并使用 BottomSheetBehavior 的默认状态对其进行初始化,例如

int state = BottomSheetBehavior.STATE_COLLAPSED;

然后,在 BottomSheetBehavior.BottomSheetCallback 中将您的 state 变量更新为当前状态

并且在 BottomSheetBehavior.STATE_DRAGGING,如果state没有展开一半,

设置状态为BottomSheetBehavior.STATE_HALF_EXPANDED

sheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
        @Override
        public void onStateChanged(@NonNull View view, int i) {
            switch (i) {
                case BottomSheetBehavior.STATE_COLLAPSED:
                    state = BottomSheetBehavior.STATE_COLLAPSED;
                    binder.imgRefresh.setVisibility(View.GONE);
                    break;
                case BottomSheetBehavior.STATE_EXPANDED:
                    binder.imgRefresh.setVisibility(View.VISIBLE);
                    state = BottomSheetBehavior.STATE_EXPANDED;
                    break;
                case BottomSheetBehavior.STATE_DRAGGING:
                    if (state != BottomSheetBehavior.STATE_HALF_EXPANDED) {
                        sheetBehavior.setState(BottomSheetBehavior.STATE_HALF_EXPANDED);
                    }
                    break;
                case BottomSheetBehavior.STATE_HALF_EXPANDED:
                    state = BottomSheetBehavior.STATE_HALF_EXPANDED;
                    break;
            }
        }

        @Override
        public void onSlide(@NonNull View view, float v) {
            binder.viewExtender.setAlpha(1 - v);
        }
    });

这将使您的 BottomSheet 采取三个步骤,即 CollapsedHalf ExpandedExpanded.

希望对大家有所帮助!

我已经尝试了 and 但不符合我想要的行为。

通过kotlin中的以下解决方案,如果你的bottomsheet滑动接近展开状态,它保持展开,如果接近一半状态,保持一半,如果它接近折叠,它保持折叠:

    val bottomSheet = view.findViewById<View>(R.id.bottom_sheet1)
    val mBottomSheetBehavior = BottomSheetBehavior.from(bottomSheet)
    mBottomSheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED
    mBottomSheetBehavior.addBottomSheetCallback(object: BottomSheetBehavior.BottomSheetCallback(){
        override fun onStateChanged(bottomSheet: View, newState: Int) {
        }

        override fun onSlide(bottomSheet: View, slideOffset: Float) {
            val upperState = 0.66
            val lowerState = 0.33
            if (bottomSheetEventsFilterBehavior.state == BottomSheetBehavior.STATE_SETTLING ) {
                if(slideOffset >= upperState){
                    mBottomSheetBehavior.state = BottomSheetBehavior.STATE_EXPANDED
                }
                if(slideOffset > lowerState && slideOffset < upperState){
                    mBottomSheetBehavior.state = BottomSheetBehavior.STATE_HALF_EXPANDED
                }
                if(slideOffset <= lowerState){
                    mBottomSheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED
                }
            }
        }
    })

最好充分利用该框架。正如官方文档所述,方法 setFitToContents :

Sets whether the height of the expanded sheet is determined by the height of its contents, or if it is expanded in two stages (half the height of the parent container, full height of parent container). Default value is true.

因此,您只需将 setFitToContent 设置为 false 即可:

behavior = BottomSheetBehavior.from(your_bottom_sheet_xml)
behavior.isFitToContents = false
behavior.halfExpandedRatio = 0.6f

使用这 3 行代码,底部 sheet 首先会扩展到屏幕的 60%,然后完全扩展到 100%。

希望对您有所帮助!

class BottomSheetFragment : BottomSheetDialogFragment() {
    /* inside of your Bottom Sheet Dialog Fragment */
    override fun onStart() {
        super.onStart()
        BottomSheetBehavior.from(requireView().parent as View).apply {
        state = BottomSheetBehavior.STATE_HALF_EXPANDED
       }
    }
}

在返回根视图之前在 onCreateView 中使用此块

dialog!!.setOnShowListener { dialog ->
        val d = dialog as BottomSheetDialog
        BottomSheetBehavior.from(requireView().parent as View).apply {
                state = BottomSheetBehavior.STATE_EXPANDED
            }
    }