Как использовать BottomSheetDialog?
Я хочу попробовать BottomSheetDialog, представленный в Android Support Library 23.2, но он работает некорректно. Вот что говорит doc:
В то время как BottomSheetBehavior фиксирует стойкий нижний регистр, этот выпуск также предоставляет BottomSheetDialog и BottomSheetDialogFragment для заполнения модального нижнего листка. Просто замените AppCompatDialog или AppCompatDialogFragment на свой нижние листы, чтобы ваш диалог был создан как нижний лист ".
Итак, я изменил свой AppCompatDialog
на BottomSheetDialog
:
package my.package.ui.dialog;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.support.design.widget.BottomSheetDialog;
import my.package.R;
public class AccountActionsDialog extends BottomSheetDialog {
public AccountActionsDialog(Context context) {
super(context);
if (context instanceof Activity) {
setOwnerActivity((Activity) context);
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getLayoutInflater().inflate(R.layout.dialog_account_actions, null));
}
}
Вот мой файл макета:
<?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="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#ff0000"
android:padding="16dp"
android:text="Delete account"
android:textColor="#ffffff" />
</LinearLayout>
Затем я использую следующий код в своей работе:
new AccountActionsDialog(this).show();
Мой экран становится тусклым, но содержимое моего диалога не отображается. Любые мысли о том, что может отсутствовать? Он отлично работает, когда я использую AppCompatDialog.
Ответы
Ответ 1
Это файл макета BottomSheetDialog.
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:soundEffectsEnabled="false">
<FrameLayout
android:id="@+id/design_bottom_sheet"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
app:layout_behavior="@string/bottom_sheet_behavior"
style="?attr/bottomSheetStyle"/>
</android.support.design.widget.CoordinatorLayout>
Ваше представление содержимого находится внутри представления design_bottom_sheet
, оно будет располагаться по центру вертикально на CoordinatorLayout
, а BottomSheetBehavior
будет его компенсировать.
mParentHeight = parent.getHeight();
mMinOffset = Math.max(0, mParentHeight - child.getHeight());
mMaxOffset = mParentHeight - mPeekHeight;
if (mState == STATE_EXPANDED) {
ViewCompat.offsetTopAndBottom(child, mMinOffset);
} else if (mHideable && mState == STATE_HIDDEN) {
ViewCompat.offsetTopAndBottom(child, mParentHeight);
} else if (mState == STATE_COLLAPSED) {
ViewCompat.offsetTopAndBottom(child, mMaxOffset);
}
Он намеревался positon design_bottom_sheet
в mMaxOffset
, но на самом деле начальный getTop дочернего представления не равен 0, а (mParentHeight - childHeight) / 2
, поэтому вы просматриваете, если смещение больше требуемого смещения.
Найдите представление design_bottom_sheet
и установите его значение силы на Gravity.TOP | Gravity.CENTER_HORIZONTAL
, чтобы исправить его. Но, если childHeight меньше, чем mPeekHeight, будет ниже области содержимого ниже вашего содержимого.
Однако, если peekHeight > childHeight
, mMaxOffset
будет меньше mMinOffset
, что вызовет странное поведение.
Возможно, код должен быть изменен на
mMaxOffset = Math.max((mParentHeight - mPeekHeight), mMinOffset);
insted
mMaxOffset = mParentHeight - child.getHeight();
Ответ 2
Я выделял ту же проблему, тусклый фон и содержимое не было видно. Вот как мне удалось обойти это, установив представление содержимого в скрытом методе setupDialog()
.
public class CustomBottomSheetDialogFragment extends BottomSheetDialogFragment {
private TextView mOffsetText;
private TextView mStateText;
private BottomSheetBehavior.BottomSheetCallback mBottomSheetBehaviorCallback = new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
setStateText(newState);
if (newState == BottomSheetBehavior.STATE_HIDDEN) {
dismiss();
}
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
setOffsetText(slideOffset);
}
};
private LinearLayoutManager mLinearLayoutManager;
private ApplicationAdapter mAdapter;
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
return super.onCreateDialog(savedInstanceState);
}
@Override
public void onViewCreated(View contentView, @Nullable Bundle savedInstanceState) {
super.onViewCreated(contentView, savedInstanceState);
}
@Override
public void setupDialog(Dialog dialog, int style) {
super.setupDialog(dialog, style);
View contentView = View.inflate(getContext(), R.layout.bottom_sheet_dialog_content_view, null);
dialog.setContentView(contentView);
mBottomSheetBehavior = BottomSheetBehavior.from(((View) contentView.getParent()));
if (mBottomSheetBehavior != null) {
mBottomSheetBehavior.setBottomSheetCallback(mBottomSheetBehaviorCallback);
}
mOffsetText = (TextView) contentView.findViewById(R.id.offsetText);
mStateText = (TextView) contentView.findViewById(R.id.stateText);
}
}
И макет:
<?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:orientation="vertical">
<TextView
android:id="@+id/offsetText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@android:color/black" />
<TextView
android:id="@+id/stateText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@android:color/black" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
Ответ 3
Здесь проблема на code.google.com https://code.google.com/p/android/issues/detail?id=201793
Проблема, которую некоторые пользователи видят, сводится к FrameLayout, которая ограничивает вертикальное отображение нашего контента. BottomSheetBehavior работает только в том случае, если это представление выровнено сверху. Я не понял, что заставляет FrameLayout центрироваться по вертикали еще, но здесь возможно обходное решение:
View contentView = ...
// You may have to measure your content view first.
dialog.setContentView(contentView);
// Change this to a percentage or a constant, whatever you want to do.
// The default is 1024 - any views smaller than this will be pulled off
// the bottom of the screen.
float peekHeight = contentView.getMeasuredHeight();
View parent = (View)contentView.getParent();
BottomSheetBehavior behavior = BottomSheetBehavior.from(parent);
behavior.setPeekHeight(peekHeight);
CoordinatorLayout.LayoutParams layoutParams =
(CoordinatorLayout.LayoutParams)parent.getLayoutParams();
layoutParams.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
Ответ 4
Он начал работать, когда я установил фиксированную высоту для моего TextView (200dp), хотя для некоторых значений высоты он по-прежнему ведет себя некорректно. Очевидно, это проблема поддержки lib. В отладчике ошибок есть несколько сообщений, связанных с BottomSheetDialog:
https://code.google.com/p/android/issues/detail?id=201793&sort=-opened&colspec=ID%20Status%20Priority%20Owner%20Summary%20Stars%20Reporter%20Opened
https://code.google.com/p/android/issues/detail?id=201826