Поддержка Android BottomSheetBehavior не может быть динамической?
Я использую нижний лист из библиотеки поддержки Android следующим образом:
XML:
<LinearLayout
android:id="@+id/bottomSheetLinearLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/fourth_white"
android:orientation="vertical"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior" />
я добавляю дочерние представления в LinearLayout:
bottomSheet.addView(actionButtonView);
после того, как я закончил добавлять дочерние представления, я инициализирую BottomSheetBehavior и расширяю его:
BottomSheetBehavior sheetBehavior = BottomSheetBehavior.from(bottomSheet);
sheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
Это не сработает. Ничего не видно. Даже если я задал высоту LinearLayout внутри XML, она просто белая.
Если я добавлю все дочерние представления внутри LinearLayout в XML, то все работать отлично. Он просто не работает, когда я пытаюсь динамически добавлять представления программно.
У кого-нибудь были подобные проблемы?
2 ответов
проблемы с динамическим контентом на BottomSheetBehavior, связанные с реализацией вычисления расширенного размера. BottomSheetBehavior вычисляет расширенный размер в методе onLayoutChild. Но при изменении содержимого макета листа процесс запускается асинхронно. Даже если вы вызываете RequestLayout или что-то подобное. Поэтому следствие звонков выглядит так:
- BottomSheetBehavior имеют старый расширенный размер (в вашем случае я думаю, что он равен нулю)
- добавить содержимое BottomSheet. Расширенный размер все еще стар.
- вы вызываете SetState в расширенный. BottomSheetBehavior все еще помнит старый расширенный размер и запускает анимацию до этого размера. Состояние изменено на STATE_SETTLING!
- onlayoutchild вызывается и BottomSheetBehavior вычисляет новый расширенный размер. Но анимация уже выполняется, и состояние STATE_SETTLING так BottomSheetBehavior не изменить его размер
- анимация закончена. Размер BottomSheet старый. Состояние изменено на Расширенный, но BottomSheetBehavior "забыл", что расширенный размер был изменен во время анимации.
это, безусловно, ошибка реализации BottomSheetBehaviour.
в моем проекте я нашел такое решение:
private void showPanel(final View panelContent) {
if (panelBehavior.getState()!=BottomSheetBehavior.STATE_EXPANDED) {
panelBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(final View bottomSheet, int newState) {
if (newState==BottomSheetBehavior.STATE_EXPANDED) {
panelBehavior.setBottomSheetCallback(null);
contentView.removeAllViews();
contentView.addView(panelContent);
panelView.setVisibility(View.VISIBLE);
}
}
@Override
public void onSlide(View bottomSheet, float slideOffset) {
}
});
panelBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
return;
}
contentView.removeAllViews();
contentView.addView(panelContent);
panelView.setVisibility(View.VISIBLE);
}
private void hidePanel() {
panelBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
panelView.setVisibility(View.GONE);
contentView.removeAllViews();
}
поэтому, когда вам нужно показать BottomSheet с новым содержимым, вызовите ShowPanel. Когда вам нужно полностью скрыть BottomSheet вызовите hidePanel (если вам нужно скрыть его в своем проекте. Если нет, вы можете удалить setVisibility из методы.)
идея обходного пути-никогда не изменять содержимое BottomSheet, когда BottomSheetBehavior не находится в расширенном состоянии. Если состояние не расширено, просто измените его на расширенное, дождитесь завершения анимации и только затем измените содержимое.
попробуйте опубликовать runnable для просмотра очереди сообщений:
bottomSheet.post(new Runnable() {
@Override
public void run() {
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}
});
или с retrolambda:
bottomSheet.post(() -> bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED));