Android - як відключити STATE_HALF_EXPANDED стан нижнього аркуша


14

У мене є нижній аркуш, який повинен переходити між двома станами, STATE_COLLAPSEDа STATE_EXPANDED коли він згортається, висота повинна бути, 200dpа коли розгорнута - це буде на весь екран.

Тому я встановлюю BottomSheetBehaviorс

isFitToContents = false
peekHeight = 200dp

і я змушений встановити значення в halfExpandedRatioіншому випадку, коли в STATE_HALF_EXPANDEDнижньому аркуші буде зайнято половину екрана.

Я працюю з / com.google.android.material:material:1.1.0-rc01

Чи є спосіб відключити STATE_HALF_EXPANDEDдержаву?

Або я повинен насправді встановити skipCollapsed=true, розібратися в співвідношенні, що означає 200dp і працювати з STATE_HALF_EXPANDEDі STATE_EXPANDEDзамість STATE_COLLAPSEDіSTATE_EXPANDED


надайте більше деталей, таких як, як виглядає нижній аркуш.
УД ..

@ UD..Я не думаю, що вміст нижнього аркуша є релевантним у цьому випадку. Це більш загальне питання, чи можна відключити один із станів нижнього аркуша
Ноа Драч

1
У моєму випадку використання, здається, що налаштування, halfExpandedRatio=0.25fа peekHeight = 200dpпотім STATE_COLLAPSEDі обробка, і STATE_HALF_EXPANDEDніби вони однакові стану, вирішує проблему. Залишайте питання відкритим у випадку, якщо є інші ідеї.
Ноа Драч

ви можете перейти за цим посиланням, це допоможе androidhive.info/2017/12/2/android-working-with-bottom-sheet
UD ..

Обов’язково прийміть одну з цих відповідей, якщо вона відповідає цілям, поставленим у вашому запитанні!
CommonsWare

Відповіді:


3

Значення напіврозширеного коефіцієнта має бути встановлене на деяке значення між 0 і 1 виключно , тому встановіть це значення на дуже низьке число, яке, безумовно, буде меншим за вашу висоту підгляду, скажімо, "0,0001f". З цією цінністю ви навіть не повинні бачити STATE_HALF_EXPANDEDдержаву. Держави будуть коливатися між STATE_EXPANDEDта STATE_COLLAPSED.


Альтернативне рішення

Вищенаведене рішення працює і ефективно відключає STATE_HALF_EXPANDEDстан, але воно є хакерським (ІМО) і може в майбутньому зламатися. Наприклад, що робити, якщо застосовується розумне значення для наполовину розгорнутого співвідношення, яке знаходиться десь між висотою підгляду та повною висотою? Це було б біда.

Вимоги, про які йдеться в ОП, полягають у тому, щоб нижній аркуш повинен був переходити між висотою погляду та повною висотою. Немає проблем із висотою підгляду, але ОП вказує isFitToContents = falseдістатись до повної висоти. (Я припускаю, що його нижній аркуш може бути коротшим, ніж наявний простір.)

На жаль, коли isFitToContents == falseвводиться додаткова поведінка на піввисоті, яку ОП хоче уникнути, а тому питання.

На додаток до поведінки "піввисоти" вводиться інша поведінка, яка є "розширеним зміщенням". Розширене зміщення визначає, наскільки далеко від повного екрана зупиниться нижній аркуш. Наприклад, значення 100f, наприклад, залишить 100pxрамку у верхній частині нижнього аркуша при повному розгортанні. За замовчуванням для розширеного зміщення дорівнює нулю.

Мені не відома будь-яка поведінка, яка isFitToContents == falseзапроваджувала б інше, ніж ті, про які було сказано вище.

Отже, враховуючи ці вимоги, чи можемо ми створити нижній аркуш, який рухається між висотою підгляду та повною висотою, уточнюючи, isFitToContents == trueтаким чином, уникаючи проблеми "половини висоти"? Немає вимоги до ненульового розширеного зміщення, тому нам не доведеться турбуватися про це.

Ось короткий демонстраційний додаток, який демонструє, що ми можемо відповідати цим вимогам за допомогою правильної структури нижнього аркуша:

введіть тут опис зображення

MainActivity5.kt

class MainActivity5 : BaseActivity() {  
    override fun onCreate(savedInstanceState: Bundle?) {  
        super.onCreate(savedInstanceState)  
        setContentView(R.layout.activity_main5)  

        val bottomSheet = findViewById<LinearLayout>(R.id.bottom_sheet)  
        val sheetBehavior: BottomSheetBehavior<LinearLayout> = BottomSheetBehavior.from(bottomSheet)  
        sheetBehavior.isFitToContents = true // the default  
  sheetBehavior.peekHeight = 200  

  // Log the states the bottom sheet passes through.  
  sheetBehavior.addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {  
            override fun onStateChanged(bottomSheet: View, newState: Int) {  
                Log.d("MainActivity", "<<<< $newState = ${translateSheetState(newState)}")  
            }  

            override fun onSlide(bottomSheet: View, slideOffset: Float) {}  
        })  
    }  
}

BaseActivity.kt

open class BaseActivity : AppCompatActivity() {  

    protected fun translateSheetState(state: Int): String {  
        return when (state) {  
            BottomSheetBehavior.STATE_COLLAPSED -> "STATE_COLLAPSED"  
  BottomSheetBehavior.STATE_DRAGGING -> "STATE_DRAGGING"  
  BottomSheetBehavior.STATE_EXPANDED -> "STATE_EXPANDED"  
  BottomSheetBehavior.STATE_HALF_EXPANDED -> "STATE_HALF_EXPANDED"  
  BottomSheetBehavior.STATE_HIDDEN -> "STATE_HIDDEN"  
  BottomSheetBehavior.STATE_SETTLING -> "STATE_SETTLING"  
  else -> "Unknown state: $state"  
  }  
    }  
}

activity_main5.xml

<androidx.coordinatorlayout.widget.CoordinatorLayout 
    android:id="@+id/main_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:id="@+id/bottom_sheet"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/holo_orange_light"
        android:orientation="vertical"
        android:scrollbars="none"
        app:layout_behavior="@string/bottom_sheet_behavior">

        <TextView
            android:id="@+id/tv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="16dp"
            android:text="@string/short_text"
            android:textSize="16sp" />

    </LinearLayout>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

Якщо у нас довгий нижній аркуш, то для його прокрутки працює наступна структура:

activity_main6.xml

<androidx.coordinatorlayout.widget.CoordinatorLayout 
    android:id="@+id/main_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:id="@+id/bottom_sheet"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/holo_orange_light"
        android:orientation="vertical"
        android:scrollbars="none"
        app:layout_behavior="@string/bottom_sheet_behavior">

        <androidx.core.widget.NestedScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <TextView
                android:id="@+id/tv"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="16dp"
                android:text="@string/long_text"
                android:textSize="16sp" />
        </androidx.core.widget.NestedScrollView>
    </LinearLayout>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

щодо вашої первинної відповіді - я побачив, що навіть якщо я встановити наполовину розгорнуте співвідношення, все ще видно дуже тонкий натяк на нижній аркуш. І все одно, це не та поведінка, яку я шукаю. як ви згадували в "Альтернативному рішенні" - "нижній аркуш повинен переходити між висотою підгляду і повною висотою"
Ноа Драч

ваше "альтернативне рішення", здається, працює, і це рішення, яке мені потрібно, моє первісне тестування показало, що мені потрібно користуватися isFitToContents = false, але тестування зараз не isFitToContents = trueпрацює / працює нормально
Ноа Драч

@NoaDrach Якщо нижній аркуш можна приховати, то внизу буде показано щонайменше 1 піксель через те, як обчислюється зміщення нижнього аркуша. Я не думав, що аркуш буде приховано, але, показуючи 1px, аркуш можна було просто приховати, sheetBehavior.state = BottomSheetBehavior.STATE_HIDDENколи буде досягнуто наполовину розширений стан, але це стає трохи складніше. Альтернативне рішення краще.
Cheticamp

2

введіть тут опис зображення

якщо ви хочете спробувати вище, як на зображенні, ви можете слідувати коду нижче, можливо, це допоможе вам !!!

public class CollectionsBottomSheet extends BottomSheetDialogFragment {
    private BottomSheetBehavior mBehavior;


    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        BottomSheetDialog dialog = (BottomSheetDialog) super.onCreateDialog(savedInstanceState);
        View view = View.inflate(getContext(), R.layout.collections_layout, null);
        LinearLayout linearLayout = view.findViewById(R.id.root);
        LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) linearLayout.getLayoutParams();
        params.height = getScreenHeight();
        linearLayout.setLayoutParams(params);
        dialog.setContentView(view);
        mBehavior = BottomSheetBehavior.from((View) view.getParent());
        return dialog;

    }

    @Override
    public void onStart() {
        super.onStart();
        mBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
    }

    public static int getScreenHeight() {
        return Resources.getSystem().getDisplayMetrics().heightPixels;
    }
}



xml 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/bottom_sheet"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/white"
    android:fitsSystemWindows="true">


    <LinearLayout
        android:id="@+id/root"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center_vertical"
            android:orientation="horizontal">

            <TextView
                android:id="@+id/filter_title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:drawableStart="@drawable/ic_cancel"
                android:drawableLeft="@drawable/ic_cancel"
                android:drawablePadding="30dp"
                android:gravity="center_vertical"
                android:padding="12dp"
                android:text="Filters"
                android:textColor="@color/black"
                android:textSize="18sp" />

            <View
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_weight="1" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginEnd="10dp"
                android:layout_marginRight="10dp"
                android:padding="5dp"
                android:text="Reset ALL"
                android:textColor="#6f6f6f"
                android:textSize="12sp" />

        </LinearLayout>

        <View
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:background="#d8dbdb" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/sort_background"
            android:drawableStart="@drawable/ic_star"
            android:drawableLeft="@drawable/ic_star"
            android:drawablePadding="15dp"
            android:padding="15dp"
            android:text="GUEST RATINGS"
            android:textColor="#6f6f6f"
            android:textSize="16sp" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/sort_background"
            android:drawableStart="@drawable/ic_money"
            android:drawableLeft="@drawable/ic_money"
            android:drawablePadding="15dp"
            android:padding="15dp"
            android:text="PRICE RANGE"
            android:textColor="#6f6f6f"
            android:textSize="16sp" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/sort_background"
            android:drawableStart="@drawable/ic_loan"
            android:drawableLeft="@drawable/ic_star"
            android:drawablePadding="15dp"
            android:padding="15dp"
            android:text="PAY AT HOTEL"
            android:textColor="#6f6f6f"
            android:textSize="16sp" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/sort_background"
            android:drawableStart="@drawable/ic_folder"
            android:drawableLeft="@drawable/ic_folder"
            android:drawablePadding="15dp"
            android:padding="15dp"
            android:text="COLLECTIONS"
            android:textColor="#6f6f6f"
            android:textSize="16sp" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/sort_background"
            android:drawableStart="@drawable/ic_perm_identity_black_24dp"
            android:drawableLeft="@drawable/ic_perm_identity_black_24dp"
            android:drawablePadding="15dp"
            android:padding="15dp"
            android:text="FACILITIES"
            android:textColor="#6f6f6f"
            android:textSize="16sp" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/sort_background"
            android:drawableStart="@drawable/ic_apartment"
            android:drawableLeft="@drawable/ic_apartment"
            android:drawablePadding="15dp"
            android:padding="15dp"
            android:text="CATEGORIES"
            android:textColor="#6f6f6f"
            android:textSize="16sp" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/sort_background"
            android:drawableStart="@drawable/ic_hotel_building"
            android:drawableLeft="@drawable/ic_hotel_building"
            android:drawablePadding="15dp"
            android:padding="15dp"
            android:text="ACCOMMODATION TYPE"
            android:textColor="#6f6f6f"
            android:textSize="16sp" />

    </LinearLayout>


</LinearLayout>

дуже хороша відповідь ... врятував мій день
unownsp

1

Спробуйте встановити addBottomSheetCallbackна своєму контекстуальному BottomSheetBehavior, і коли ви виявили STATE_HALF_EXPANDEDстан, викличте setState(STATE_HIDDEN)тому , коли нижній лист намагається досягти стану на півдорозі, це буде просто близько.


приємна ідея, в моєму випадку я би встановив стан STATE_COLLAPSEDі ні STATE_HIDDEN. Але я намагався здійснити це і перехід від STATE_HALF_EXPANDEDдо STATE_COLLAPSEDпочувається незграбною. Перехід між станами анімований, тож ви бачите, що нижній аркуш зупиняється на, STATE_HALF_EXPANDEDа потім він переходить доSTATE_COLLAPSED
Ноа Драч

Не могли б ви поєднати це з половиною розширеного коефіцієнта 0?
Ridcully

@Ridcully - 2 випуски тут - 1. halfExpandedRatio повинен бути вище 0 2. Якщо встановити його на дуже низьке значення, це призведе до того, що він буде зведений до мене майже повністю (наполовину розширений стан), перш ніж перейти до стану згорнутого стану. Я думав поєднати цю пропозицію з моїм робочим рішенням halfExpandedState=0.25f, b / c, тоді перехід між станами не буде таким очевидним. Але я не впевнений, що це буде велика зміна порівняно з тим, що я вже маю
Ноа Драч

1

У мене був подібний випадок використання, коли макет повинен був становити третину висоти. Я спробував наступне, і це спрацювало чудово.

<androidx.coordinatorlayout.widget.CoordinatorLayout 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_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/grey"
    android:clickable="true">

    <LinearLayout
        android:id="@+id/bottom_sheet"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/rounded_bottom_sheet_background"
        android:orientation="vertical"
        app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recycler"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </LinearLayout>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

Мені довелося змінити це динамічно, тому я встановив наступне на нижньому аркуші, але ви можете це зробити так само в xml:

bottomSheet.setPeekHeight(200);// 200px
bottomSheet.setHideable(false);

Для відхилення я додав анімацію до свого фрагмента за допомогою наступної функції:

fragmentTransaction.setCustomAnimations(
                    R.anim.fade_in,
                    R.anim.fade_out,
                    R.anim.fade_in,
                    R.anim.fade_out)

Сподіваюсь, це допомагає


1

Спробуйте встановити BottomSheetBehavior.setHalfExpandedRatio(0f). Існує не так багато іншого, що вплине STATE_HALF_EXPANDED, якщо явно не встановити стан за допомогою .setState () . Слід також мати можливість створити звичай Behavior, який розширюється CoordinatorLayout.Behavior<View>і не має STATE_HALF_EXPANDED. напр. Перехоплення всього за допомогою поведінки CoordinatorLayout .


0

Я пробував різні способи, але жодна техніка не працювала ідеально. Я спробував перехопити події BottomSheetBehavior.BottomSheetCallback {}і зателефонував dismiss()на основі власної логіки, але це спричинило ривок.

Отже, нарешті, у своєму " BottomSheetDialogFragmentЯ додав", bottomSheetBehavior.isDraggable = falseі це спричинило перетягування нижнього аркуша на дотик І, я самостійно займався відхиленням діалогу. у діалоговому вікні порожньої області все одно звільняють.

Зауважте, що нижній аркуш все ще розширюється анімацією. Це 'справді чудово!

переосмислити розваги onCreateDialog (збереженийInstanceState: Пакет?): діалог {val діалог = super.onCreateDialog (збереженийInstanceState)

    dialog.setOnShowListener {
        val bottomSheetDialog = it as BottomSheetDialog
        val bottomSheet =
            bottomSheetDialog.findViewById<View>(com.google.android.material.R.id.design_bottom_sheet)
                ?: return@setOnShowListener

        //Making background to transparent to avoid white background to given space margin.
        bottomSheet.setBackgroundColor(ContextCompat.getColor(context!!, R.color.transparent))

        val inflatedView = fragmentProfileDialogBinding.root
        val parent = inflatedView.parent as View

        val bottomSheetBehavior = BottomSheetBehavior.from(parent)
        bottomSheetBehavior.state = BottomSheetBehavior.STATE_EXPANDED
        bottomSheetBehavior.isDraggable = false
    }

    return dialog
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.