BottomSheetDialogFragment - Как установить расширенную высоту (или минимальное смещение)
Я создаю BottomSheetDialogFragment
, и я хочу настроить его максимальную расширенную высоту. Как я могу это сделать? Я могу получить BottomSheetBehaviour
, но все, что я могу найти, это наборщик высоты заглядывания, но ничего для расширенной высоты.
public class DialogMediaDetails extends BottomSheetDialogFragment
{
@Override
public void setupDialog(Dialog dialog, int style)
{
super.setupDialog(dialog, style);
View view = View.inflate(getContext(), R.layout.dialog_media_details, null);
dialog.setContentView(view);
...
View bottomSheet = dialog.findViewById(R.id.design_bottom_sheet);
BottomSheetBehavior behavior = BottomSheetBehavior.from(bottomSheet);
behavior.setPeekHeight(...);
// how to set maximum expanded height???? Or a minimum top offset?
}
}
ИЗМЕНИТЬ
Зачем мне это нужно? Потому что я показываю диалог BottomSheet
в полноэкранном режиме и выглядит плохо, если BottomSheet
оставляет место сверху...
Ответы
Ответ 1
Высота оборачивается из-за того, что раздутый вид добавляется в FrameLayout, который имеет layout_height=wrap_content
. См. FrameLayout (R.id.design_bottom_sheet) на https://github.com/dandar3/android-support-design/blob/master/res/layout/design_bottom_sheet_dialog.xml.
Приведенный ниже класс делает нижний лист полноэкранным, фон прозрачным и полностью раскрытым.
public class FullScreenBottomSheetDialogFragment extends BottomSheetDialogFragment {
@CallSuper
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ButterKnife.bind(this, view);
}
@Override
public void onStart() {
super.onStart();
Dialog dialog = getDialog();
if (dialog != null) {
View bottomSheet = dialog.findViewById(R.id.design_bottom_sheet);
bottomSheet.getLayoutParams().height = ViewGroup.LayoutParams.MATCH_PARENT;
}
View view = getView();
view.post(() -> {
View parent = (View) view.getParent();
CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) (parent).getLayoutParams();
CoordinatorLayout.Behavior behavior = params.getBehavior();
BottomSheetBehavior bottomSheetBehavior = (BottomSheetBehavior) behavior;
bottomSheetBehavior.setPeekHeight(view.getMeasuredHeight());
((View)bottomSheet.getParent()).setBackgroundColor(Color.TRANSPARENT)
});
}
}
--- ОБНОВЛЕНИЕ 30 августа 2018 г. ---
Год спустя я понял, что фон был окрашен при неправильном просмотре. это перетаскивало фон вместе с содержимым, пока пользователь перетаскивал диалог.
Я исправил это так, чтобы родительский вид нижнего листа был цветным.
Ответ 2
Я нашел гораздо более простой ответ; в вашем примере, где вы получаете FrameLayout для нижнего листа, используя этот код
View bottomSheet = dialog.findViewById(R.id.design_bottom_sheet);
вы можете установить высоту в параметрах макета для этого представления для любой высоты, на которую вы хотите установить расширенную высоту.
bottomSheet.getLayoutParams().height = ViewGroup.LayoutParams.MATCH_PARENT;
Ответ 3
БОЛЬШОЕ ОБНОВЛЕНИЕ
Чтобы избежать дублирования кода, я даю ссылку на полный ответ, где вы можете найти все объяснения о том, как получить полное поведение, например, Карты Google.
Я хочу настроить максимальную расширенную высоту. Как я могу это сделать?
Оба BottomSheet
и BottomSheetDialogFragment
используют BottomSheetBehavior, который вы можете найти в библиотеке поддержки 23.x
Этот класс Java имеет 2 различных использования для mMinOffset
, один из них используется для определения области родителя, которую он будет использовать для рисования своего контента (возможно, NestedScrollView
). И другой вариант, если для определения расширенной точки привязки, я имею в виду, если вы сдвинете ее вверх по форме STATE_COLLAPSED
, она будет анимировать ваш BottomSheet
, пока он не достигнет этой точки привязки, НО, если вы все еще можете продолжать скользить вверх, чтобы покрыть всю родительскую высоту (Высота CoordiantorLayout).
Если вы взглянули на BottomSheetDialog
, вы увидите этот метод:
private View wrapInBottomSheet(int layoutResId, View view, ViewGroup.LayoutParams params) {
final CoordinatorLayout coordinator = (CoordinatorLayout) View.inflate(getContext(),
android.support.design.R.layout.design_bottom_sheet_dialog, null);
if (layoutResId != 0 && view == null) {
view = getLayoutInflater().inflate(layoutResId, coordinator, false);
}
FrameLayout bottomSheet = (FrameLayout) coordinator.findViewById(android.support.design.R.id.design_bottom_sheet);
BottomSheetBehavior.from(bottomSheet).setBottomSheetCallback(mBottomSheetCallback);
if (params == null) {
bottomSheet.addView(view);
} else {
bottomSheet.addView(view, params);
}
// We treat the CoordinatorLayout as outside the dialog though it is technically inside
if (shouldWindowCloseOnTouchOutside()) {
final View finalView = view;
coordinator.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (isShowing() &&
MotionEventCompat.getActionMasked(event) == MotionEvent.ACTION_UP &&
!coordinator.isPointInChildBounds(finalView,
(int) event.getX(), (int) event.getY())) {
cancel();
return true;
}
return false;
}
});
}
return coordinator;
}
Не знаю, какое из этих двух способов поведения вам нужно, но если вам нужно второе, выполните следующие действия:
- Создайте класс Java и расширьте его из
CoordinatorLayout.Behavior<V>
- Скопируйте код вставки из файла по умолчанию
BottomSheetBehavior
в новый.
Измените метод clampViewPositionVertical
с помощью следующего кода:
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
return constrain(top, mMinOffset, mHideable ? mParentHeight : mMaxOffset);
}
int constrain(int amount, int low, int high) {
return amount < low ? low : (amount > high ? high : amount);
}
Добавить новое состояние
public static final int STATE_ANCHOR_POINT = X;
Измените следующие методы: onLayoutChild
, onStopNestedScroll
, BottomSheetBehavior<V> from(V view)
и setState
(необязательно)
А вот как это выглядит:
[
]
Ответ 4
Котлин
В моем случае мне нужно определить фиксированную высоту, и я сделал следующее:
val bottomSheet: View? = dialog.findViewById(R.id.design_bottom_sheet)
BottomSheetBehavior.from(bottomSheet!!).peekHeight = 250
таким образом, у вас также есть доступ к любому свойству BottomSheetBehavior
, например halfExpandedRatio