Как я могу установить полурасширенное состояние для моего нижнего листа

У меня есть макет с нижним листом.

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

Компоновка нижнего листа

 <?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>

Мне нужно, чтобы мой нижний лист открывался первой половиной, а после повторного перетаскивания открывался на весь экран. Как это делается в приложении Google Maps. Но я понятия не имею, как это сделать.


person Sergei Buvaka    schedule 03.04.2019    source источник


Ответы (4)


Лучше использовать фреймворк на полную мощность. Как указано в официальной документации для метода setFitToContents :

Устанавливает, определяется ли высота развернутого листа высотой его содержимого или он расширяется в два этапа (половина высоты родительского контейнера, полная высота родительского контейнера). Значение по умолчанию — истина.

Итак, все, что вам нужно, это установить setFitToContent в false с помощью:

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

С этим 3-строчным кодом нижний лист сначала расширится до 60% экрана, а затем полностью расширится до 100%.

Надеюсь, поможет!

person Adauton Heringer    schedule 12.12.2019
comment
полурасширенное соотношение? - person Arnold Brown; 29.06.2020
comment
@ArnoldBrown доступен в версии 1.1.0-alpha05. - person Илья Имхолинкс; 28.07.2020
comment
спас мой день!! Спасибо за понимание - person Sandy; 06.05.2021

Просто установите для состояния BottomSheetBehaivor значение BottomSheetBehavior.STATE_HALF_EXPANDED. Кроме того, если вам нужно после полного расширения позволить пользователю снова вернуться в режим наполовину расширенного, вам нужно установить высоту просмотра на половину высоты окна.

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

Я пробовал @Massab и @HeyAlex, но не соответствует моему желаемому поведению.

Со следующим решением в kotlin, если ваше скольжение нижнего листа близко к расширенному состоянию, оно остается расширенным, если оно близко к половинному состоянию, остается наполовину, а если оно почти свернуто, оно остается свернутым:

    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
                }
            }
        }
    })
person david    schedule 15.11.2019
comment
это нарушает поведение броска - person Kochchy; 30.06.2020
comment
Спасибо @Kochchy, я согласен, я рекомендую это решение stackoverflow.com/a/59305687/2989387 - person david; 09.07.2020

Хотя на этот вопрос был дан ответ, но просто появился другой способ реализовать это поведение, чтобы поделиться им с другими.

Создайте глобальную переменную и инициализируйте ее состоянием по умолчанию вашего BottomSheetBehavior, например

int state = BottomSheetBehavior.STATE_COLLAPSED;

Затем в BottomSheetBehavior.BottomSheetCallback обновите переменную state до текущего состояния.

и в BottomSheetBehavior.STATE_DRAGGING, если состояние не развернуто наполовину,

установите состояние 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 выполнить три шага , т. е. Свернуто, Наполовину развернуто, Расширено.

Надеюсь, это может помочь кому-то!

person Massab    schedule 19.09.2019
comment
как насчет onSlide. я хочу, чтобы положение на полпути рассматривалось так, как если бы карта уже скользнула вверх. но я вижу, что смещение onSlide по-прежнему составляет процент от общего экрана. - person j2emanue; 17.06.2020