Динамически менять высоту BottomSheetBehavior
Я использую BottomSheetBehavior
из недавно выпущенного AppCompat v23.2 от Google. Высота моего нижнего листа зависит от содержимого, отображаемого внутри нижнего листа (аналогично тому, что делает Google в приложении "Карты" ).
Он отлично работает с первоначально загруженными данными, но мое приложение меняет содержимое, отображаемое во время выполнения, и когда это происходит, нижний лист сохраняет на нем прежнюю высоту, что либо приводит к неиспользуемому пространству внизу, либо к разрезу.
Есть ли способ сообщить макет нижнего листа для пересчета высоты, используемой для расширенного состояния (когда высота ViewGroup
установлена на MATCH_HEIGHT
) или каким-либо способом вручную установить требуемую высоту?
EDIT: Я также попытался вручную вызвать invalidate()
на ViewGroup
и родительский элемент, но без каких-либо успехов.
Ответы
Ответ 1
У меня была та же проблема с 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);
Ответ 2
Вы можете использовать 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);
Ответ 3
Хотя проблема была решена в библиотеке поддержки >= 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) {
}
});
Ответ 4
Я столкнулся с такой же проблемой, пытаясь обновить высоту заглядывания на основе ее содержимого, была найдена высота от предыдущего макета. Это имеет смысл, поскольку новый макет еще не состоялся. По проводке в потоке пользовательского интерфейса высота макета вычисляется после нового макета, и выполняется другой запрос макета, чтобы обновить нижний лист до нужной высоты.
void show() {
setVisibility(View.VISIBLE);
post(new Runnable() {
@Override
public void run() {
mBottomSheetBehavior.setPeekHeight(findViewById(R.id.sheetPeek).getHeight());
requestLayout();
}
})
}
Ответ 5
У меня возникла такая же проблема, когда я использовал recyclerview внутри BottomSheet, и элементы менялись динамически. Как отметил @sosite в своем комментарии, проблема регистрируется, и они исправили ее в последней версии.
Журнал проблем здесь
Просто обновите свою библиотеку поддержки дизайна до версии 24.0.0 и проверьте.
Ответ 6
Я следовал совету @HaraldUnander, и он дал мне идею, которая действительно сработала. Если вы запустили поток (не смог заставить его работать с методом post как он) после того, как BottomSheetBehavior.state
программно STATE_COLLAPSED
на STATE_COLLAPSED
, то вы уже можете получить высоту ваших представлений и установить peekHeight
зависимости от его содержимого.
Итак, сначала вы устанавливаете BottomSheetBehavior
:
BottomSheetBehavior.from(routeCaptionBottomSheet).state = BottomSheetBehavior.STATE_COLLAPSED
И тогда вы устанавливаете peekHeight динамически:
thread {
activity?.runOnUiThread {
val dynamicHeight = yourContainerView.height
BottomSheetBehavior.from(bottomSheetView).peekHeight = dynamicHeight
}
}
Если используется Java (я использую Kotlin с Anko для потоков), это может сделать:
new Thread(new Runnable() {
public void run() {
val dynamicHeight = yourContainerView.height
BottomSheetBehavior.from(bottomSheetView).peekHeight = dynamicHeight
}
}).start();