Динамически менять высоту BottomSheetBehavior

Я использую BottomSheetBehavior от недавно выпущенного AppCompat v23.2 от Google. Высота моего нижнего листа зависит от содержимого, отображаемого внутри нижнего листа (аналогично тому, что Google делает в своем приложении «Карты»).

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

Есть ли способ сообщить макет нижнего листа для пересчета высоты, используемой для расширенного состояния (когда высота ViewGroup установлена ​​в MATCH_HEIGHT ) или любым способом вручную установить требуемую высоту?


EDIT: Я также попытался вручную вызвать invalidate() в ViewGroup и родительском ViewGroup но без каких-либо успехов.

Solutions Collecting From Web of "Динамически менять высоту BottomSheetBehavior"

У меня была та же проблема с RelativeLayout что и мой нижний лист. Высота не будет пересчитана. Мне пришлось прибегнуть к настройке высоты по новому пересчитанному значению и вызову BottomSheetBehavior.onLayoutChild .

Это мое временное решение:

 coordinatorLayout = (CoordinatorLayout)findViewById(R.id.coordinator_layout); bottomSheet = findViewById(R.id.bottom_sheet); int accountHeight = accountTextView.getHeight(); accountTextView.setVisibility(View.GONE); bottomSheet.getLayoutParams().height = bottomSheet.getHeight() - accountHeight; bottomSheet.requestLayout(); behavior.onLayoutChild(coordinatorLayout, bottomSheet, ViewCompat.LAYOUT_DIRECTION_LTR); 

Для этого вы можете использовать BottomSheetBehavior#setPeekHeight .

 FrameLayout bottomSheet = (FrameLayout) findViewById(R.id.bottom_sheet); BottomSheetBehavior<FrameLayout> behavior = BottomSheetBehavior.from(bottomSheet); behavior.setPeekHeight(newHeight); 

Это не автоматически перемещает нижний лист на высоту заглядывания. Вы можете вызвать BottomSheetBehavior#setState чтобы настроить нижний лист на новую высоту заглядывания.

 behavior.setState(BottomSheetBehavior.STATE_COLLAPSED); 

Я столкнулся с той же проблемой, когда использовал recyclerview внутри BottomSheet, и элементы менялись динамически. Как отметил @sosite в своем комментарии, проблема регистрируется, и они исправили ее в последней версии. Журнал ошибок здесь

Просто обновите свою библиотеку поддержки дизайна до версии 24.0.0 и проверьте.

Хотя проблема была решена в библиотеке поддержки> = 24.0.0, если по какой-то причине вам все равно придется использовать более старую версию, это обходное решение.

 mBottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() { @Override public void onStateChanged(@NonNull final View bottomSheet, int newState) { bottomSheet.post(new Runnable() { @Override public void run() { //workaround for the bottomsheet bug bottomSheet.requestLayout(); bottomSheet.invalidate(); } }); } @Override public void onSlide(@NonNull View bottomSheet, float slideOffset) { } }); 

Я столкнулся с той же проблемой, пытаясь обновить высоту заглядывания на основе ее содержимого, была найдена высота от предыдущего макета. Это имеет смысл, поскольку новый макет еще не состоялся. По проводке в потоке пользовательского интерфейса высота макета вычисляется после нового макета, и выполняется другой запрос макета, чтобы обновить нижний лист до нужной высоты.

 void show() { setVisibility(View.VISIBLE); post(new Runnable() { @Override public void run() { mBottomSheetBehavior.setPeekHeight(findViewById(R.id.sheetPeek).getHeight()); requestLayout(); } }) }