I have implemented a BottomSheet Dialog and I want to prevent the bottomsheet from dismissing when the user touches outside of the bottomsheet when it's peeking (Not fully expanded state).
I have set dialog.setCanceledOnTouchOutside(false);
in the code but it doesn't seem to take any affect.
Here's my BottomSheetDialogFragment class:
public class ShoppingCartBottomSheetFragment extends BottomSheetDialogFragment {
private BottomSheetBehavior.BottomSheetCallback mBottomSheetBehaviorCallback = new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
if (newState == BottomSheetBehavior.STATE_HIDDEN) {
dismiss();
}
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
}
};
@Override
public void setupDialog(Dialog dialog, int style) {
super.setupDialog(dialog, style);
View contentView = View.inflate(getContext(), R.layout.fragment_shopping_cart_bottom_sheet, null);
dialog.setCanceledOnTouchOutside(false);
dialog.setContentView(contentView);
CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) ((View) contentView.getParent()).getLayoutParams();
CoordinatorLayout.Behavior behavior = params.getBehavior();
if( behavior != null && behavior instanceof BottomSheetBehavior ) {
((BottomSheetBehavior) behavior).setBottomSheetCallback(mBottomSheetBehaviorCallback);
((BottomSheetBehavior) behavior).setPeekHeight(97);
((BottomSheetBehavior) behavior).setHideable(false);
}
}
@Override
public void onStart() {
super.onStart();
Window window = getDialog().getWindow();
WindowManager.LayoutParams windowParams = window.getAttributes();
windowParams.dimAmount = 0;
windowParams.flags |= WindowManager.LayoutParams.FLAG_DIM_BEHIND;
window.setAttributes(windowParams);
}
}
According to the BottomSheet specification bottom sheets can be dismissed by touching outside of the bottom sheet, therefore what are my options to override this behavior and prevent it being dismissed?
You should use #setCancelable(false)
when you create an instance of it.
BottomSheetDialogFragment bottomSheetDialogFragment = new SequenceControlFragmentBottomSheet();
bottomSheetDialogFragment.setCancelable(false);
bottomSheetDialogFragment.show(getChildFragmentManager(), bottomSheetDialogFragment.getTag());
setCancelable(false)
will prevent the bottom sheet dismiss on back press also. If we look at the layout resource for the bottom sheet in android design support library, there is a View component with ID touch_outside
and there is an OnClickListener
set in method wrapInBottomSheet
of BottomSheetDialog
, which is used for detecting clicks outside and dismiss the dialog. So, to prevent cancel on touch outside the bottom sheet we need to remove the OnClickListener
.
Add these line to onActivityCreated
method (or any other life cycle method after onCreateView
).
@Override public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
View touchOutsideView = getDialog().getWindow()
.getDecorView()
.findViewById(android.support.design.R.id.touch_outside);
touchOutsideView.setOnClickListener(null);
}
Also if you want to prevent the bottom sheet dismiss by swiping down, change the bottom sheet dialog behaviour Hideable false. To setHideable(false)
add the following code to the onCreateDialog
method.
@Override public Dialog onCreateDialog(Bundle savedInstanceState) {
final BottomSheetDialog bottomSheetDialog =
(BottomSheetDialog) super.onCreateDialog(savedInstanceState);
bottomSheetDialog.setOnShowListener(new DialogInterface.OnShowListener() {
@Override public void onShow(DialogInterface dialog) {
FrameLayout bottomSheet =
bottomSheetDialog.findViewById(android.support.design.R.id.design_bottom_sheet);
if (null != bottomSheet) {
BottomSheetBehavior behavior = BottomSheetBehavior.from(bottomSheet);
behavior.setHideable(false);
}
}
});
return bottomSheetDialog;
}
来源:https://stackoverflow.com/questions/42154321/prevent-dismissal-of-bottomsheetdialogfragment-on-touch-outside