Проблема с нижним листом
Я получаю неправильное поведение при показе диалога Bottom Sheet в ландшафтном режиме. Проблема возникает в версии 24. + библиотеки дизайна.
В соответствии с приведенным ниже изображением нижний лист отображается некорректно только в ландшафте. Я использую класс BottomSheetDialog, и я следую этому руководству: http://www.skholingua.com/blog/bottom-sheet-android, в моих опубликованных приложениях проблема также возникает.
Я тестировал версию 25. +, и проблема не была решена.
Ошибка в ландшафте 24, 25. + Библиотека
![Ошибка в ландшафте]()
Тот же пример в 23. + Library
![тот же пример в 23. + Library]()
Основная деятельность
public class MainActivity extends AppCompatActivity {
CoordinatorLayout coordinatorLayout;
private BottomSheetBehavior<View> mBottomSheetBehavior;
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
coordinatorLayout = (CoordinatorLayout) findViewById(R.id.main_content);
textView = (TextView) findViewById(R.id.textView);
View bottomSheet = coordinatorLayout.findViewById(R.id.bottom_sheet);
//For your bottom sheet to be displayable, you need to create a BottomSheetBehavior.
//This is created by getting a reference to the container view and calling BottomSheetBehavior.from() on that container.
mBottomSheetBehavior = BottomSheetBehavior.from(bottomSheet);
mBottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
switch (newState) {
case BottomSheetBehavior.STATE_DRAGGING:
break;
case BottomSheetBehavior.STATE_COLLAPSED:
mBottomSheetBehavior.setPeekHeight(0);
break;
case BottomSheetBehavior.STATE_EXPANDED:
break;
case BottomSheetBehavior.STATE_HIDDEN:
break;
case BottomSheetBehavior.STATE_SETTLING:
break;
}
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
}
});
}
public void onClick(View v) {
switch (v.getId()) {
case R.id.button1:
/**
* For persistent bottom sheet to work, your layout should contain a coordinator layout,
* and then in any child view of your coordinator layout, you can make it as a persistent bottom sheet
* by adding a custom property app:layout_behavior and use behavior_peekHeight to define how much
* of the Bottom Sheet you want visible.
*/
textView.setText(R.string.dynamic_persistent_txt);
mBottomSheetBehavior.setPeekHeight(300);
mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
break;
case R.id.button2:
/**
* You can also display a Dialog in place of a View in the bottom sheet.
* To do this, get the view from getLayoutInflater and pass it setContentView of the Dialog.
*/
View view = getLayoutInflater().inflate(R.layout.bottom_sheet_layout, null);
TextView textView = (TextView) view.findViewById(R.id.textView);
textView.setText(R.string.dialog_modal_txt);
BottomSheetDialog dialog = new BottomSheetDialog(this);
dialog.setContentView(view);
dialog.show();
break;
case R.id.button3:
/**
* You can also display a Fragment in place of a View in the bottom sheet.
* To do this, you class that extends BottomSheetDialogFragment.
*/
BottomSheetDialogFragment bottomSheetDialogFragment = new BottomSheetDialogFragmentExample();
bottomSheetDialogFragment.show(getSupportFragmentManager(), bottomSheetDialogFragment.getTag());
break;
}
}
activity_main.xml
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingTop="24dp"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<Button
android:id="@+id/button1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="Dynamic BottomSheet" />
<Button
android:id="@+id/button2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="BottomSheetDialog" />
<Button
android:id="@+id/button3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="BottomSheetDialogFragment" />
</LinearLayout>
<LinearLayout
android:id="@+id/bottom_sheet"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elevation="4dp"
android:minHeight="120dp"
android:orientation="vertical"
android:padding="@dimen/activity_vertical_margin"
app:behavior_peekHeight="120dp"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior">
<include layout="@layout/bottom_sheet_layout" />
</LinearLayout>
</android.support.design.widget.CoordinatorLayout>
bottom_sheet_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/CreamyGreen"
android:orientation="vertical">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/static_persistent_txt"
android:padding="16dp"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@android:color/white" />
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
android:text="@string/ipsum"
android:textColor="@android:color/white"
android:textSize="16sp" />
</LinearLayout>
Ответы
Ответ 1
Это работа. (Примечание: этот код находится в действии)
View sheetView;//class level variable
private void setUpBottomSheetDialog() {
bottomSheetDialog = new BottomSheetDialog(this);
LayoutInflater inflater = LayoutInflater.from(this);
sheetView = inflater.inflate(R.layout.bottom_sheet_image_source, (ViewGroup) this.getWindow().getDecorView().getRootView(), false);
bottomSheetDialog.setContentView(sheetView);
BottomSheetBehavior mBehavior = BottomSheetBehavior.from((View) sheetView.getParent());
bottomSheetDialog.setOnShowListener(dialogInterface -> {
mBehavior.setPeekHeight(sheetView.getHeight());//get the height dynamically
});
}
Ответ 2
Ребята из Google закрыли это, работая по назначению, вот обходной путь
Существует волшебная константа отношения высоты экрана, которая, кажется, делает min (фактическая ширина, ширина), которая, очевидно, не работает хорошо
с ландшафтами телефона, поэтому переопределите его на нечто большее
<style name="Theme.Main.Reader">
...
<item name="bottomSheetDialogTheme">@style/ReaderBottomSheelDialog</item>
</style>
<style name="ReaderBottomSheelDialog" parent="Theme.Design.BottomSheetDialog">
<item name="bottomSheetStyle">@style/BottomSheetStyle</item>
</style>
<style name="BottomSheetStyle" parent="Widget.Design.BottomSheet.Modal">
<item name="behavior_peekHeight">512dp</item>
</style>
Ответ 3
Мой личный выбор для решения этой проблемы: после onCreateView у вас уже есть основной вид BottomSheetDialogFragment.
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
mainLayout = inflater.inflate(R.layout.fragment_auction_bottom_sheet_dialog, container, false);
return mainLayout;
}
И onStart будет выполнен после того, как вы создадите View, так что вы можете поиграть с поведением:
@Override
public void onStart() {
super.onStart();
//this expands the bottom sheet even after a config change
bottomSheetBehavior = BottomSheetBehavior.from((View) mainLayout.getParent());
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}
Тогда у вас всегда будет развернут Нижний лист
Ответ 4
Для того, чтобы BottomSheetDialogFragment всегда открывался полностью расширенным (также в ландшафтном режиме), я делаю следующее.
В onCreateDialog вы создаете BottomSheetDialog и ваше представление. После добавления этого представления в BottomSheetDialog вы можете получить BottomSheetBehavior, используя родительский элемент вашего представления в BottomSheetBehavior.from().
Затем в onStart из BottomSheetDialogFragment вы вызываете BottomSheetBehavior.setState с STATE_EXPANDED.
BottomSheetBehavior mBottomBehavior;
public Dialog onCreateDialog(Bundle savedInstanceState) {
BottomSheetDialog dialog = new BottomSheetDialog(getContext());
mBinding = SomeBinding.inflate(LayoutInflater.from(getContext()));
dialog.setContentView(mBinding.getRoot());
mBottomBehavior = BottomSheetBehavior.from((View) mBinding.getRoot().getParent());
return dialog;
}
public void onStart() {
super.onStart();
mBottomBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}
Я надеюсь, что это поможет кому-то.
Ответ 5
Диалог BottomSheetDialog; BottomSheetBehavior bottomSheetBehavior;
private void createBottomSheet() {
if (dialog == null){
dialog = new BottomSheetDialog(this);
final View view = LayoutInflater.from(this).inflate(R.layout.setting_dialog,
(ViewGroup)this.getWindow().getDecorView().getRootView(),false);
dialog.setContentView(view);
bottomSheetBehavior = BottomSheetBehavior.from((View)view.getParent());
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(DialogInterface dialog) {
bottomSheetBehavior.setPeekHeight(view.getHeight());
}
});
}
}
Ответ 6
В AndroidX нижний лист может быть расширен следующим образом:
BottomSheetDialog bottomSheetDialog =
new BottomSheetDialog(requireContext());
bottomSheetDialog.setContentView(view);
bottomSheetDialog.show();
FrameLayout bottomSheet = (FrameLayout)
bottomSheetDialog.findViewById(com.google.android.material.R.id.design_bottom_sheeet);
BottomSheetBehavior behavior = BottomSheetBehavior.from(bottomSheet);
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
behavior.setPeekHeight(0);
Это также будет полезно в случае следующей ошибки при получении поведения нижнего листа:
"мнение не является дочерним по отношению к координатору"