I am working on BottomSheetDialogFragment
my requirement is to create Bottom menu,
Where if I click outside fragment area it should not cancel the Dialog and should persist.
ISSUE: And Event outside the Fragment should propagate to the lower fragment view/fragment.
I have already tried below(doesn't work for BottomDialogFragment): Allow outside touch for DialogFragment
To stop the dialog cancel i tried Below(i call setCancelable(boolean)
in onStart()
of BottomDialogFragment):
@Override
public void setCancelable(boolean cancelable) {
super.setCancelable(cancelable);
BottomSheetDialog dialog = (BottomSheetDialog) getDialog();
dialog.setCanceledOnTouchOutside(cancelable);
View bottomSheetView = dialog.getWindow().getDecorView().findViewById(R.id.design_bottom_sheet);
BottomSheetBehavior.from(bottomSheetView).setHideable(cancelable);
}
reference
EDIT: Found it the hard way there is no other go then using Coordinate layout.The best solution for BottomSheetDialog is here
Try code below in your BottomSheetDialog
:
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return (super.onCreateDialog(savedInstanceState) as BottomSheetDialog).apply {
setCanceledOnTouchOutside(false)
}
}
or wrap by <CoordinatorLayout>
for instance your <ConstraintLayout>
and implement <layout />
and attach to BottomSheetBehavior
.
As been said by Pankaj Kumar, this is not possible by default. However, I found a workaround that works and allows touches to views outside of the bottom sheet while keeping the bottom sheet open
You can override the layout of the BottomSheetDialog
like so:
values/refs.xml
<resources xmlns:tools="http://schemas.android.com/tools">
<item name="design_bottom_sheet_dialog" type="layout" tools:override="true">@layout/custom_design_bottom_sheet_dialog</item>
</resources>
layout/custom_design_bottom_sheet_dialog.xml
<?xml version="1.0" encoding="utf-8"?>
<!--
~ This is an override of the design_bottom_sheet_dialog from material library
-->
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/coordinator"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<View
android:id="@+id/touch_outside"
android:layout_width="0dp"
android:layout_height="0dp"
android:visibility="gone"
android:importantForAccessibility="no"
android:soundEffectsEnabled="false"
tools:ignore="UnusedAttribute"/>
<FrameLayout
android:id="@+id/design_bottom_sheet"
style="?attr/bottomSheetStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|top"
app:layout_behavior="@string/bottom_sheet_behavior"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</FrameLayout>
YourCustomBottomSheetDialogFragment
override fun onStart() {
super.onStart()
// Set layout for custom bottom sheet by allowing background touches
dialog?.window?.apply {
setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL)
attributes = attributes.apply {
gravity = Gravity.BOTTOM
}
setDimAmount(0.0f)
}
}
By doing this, the dialog has a wrap_content
height and the flags allow touches to be handled by views outside of this dialog
you should use android.support.design.widget.BottomSheetBehavior
.
but if you want to have a bottomSheet
in other class I suggest you use a Fragment
and in this fragment
open your bottomSheet
open your fragment in this way.
And in your fragment, open your bottomSheet
in the following code:
in onInitViews
var mBottomSheetBehavior = BottomSheetBehavior.from(bottomSheetCoordinatorLayout)
mBottomSheetBehavior!!.state = BottomSheetBehavior.STATE_HIDDEN
mBottomSheetBehavior!!.setBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
override fun onStateChanged(bottomSheet: View, newState: Int) {
when (newState) {
BottomSheetBehavior.STATE_HIDDEN -> {
fragmentManager?.popBackStack()
}
//BottomSheetBehavior.STATE_COLLAPSED -> "Collapsed"
//BottomSheetBehavior.STATE_DRAGGING -> "Dragging..."
//BottomSheetBehavior.STATE_EXPANDED -> "Expanded"
//BottomSheetBehavior.STATE_SETTLING -> "Settling..."
}
}
override fun onSlide(bottomSheet: View, slideOffset: Float) {
//text_view_state!!.text = "Sliding..."
}
})
And your layout
should be like this:
<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:layoutDirection="ltr">
<android.support.design.widget.CoordinatorLayout
android:id="@+id/bottomSheetCoordinatorLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:behavior_hideable="true"
app:behavior_peekHeight="55dp"
app:layout_behavior="@string/bottom_sheet_behavior">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/top_radius_primary_color"
android:paddingStart="@dimen/material_size_32"
android:paddingEnd="@dimen/material_size_32">
</RelativeLayout>
</android.support.design.widget.CoordinatorLayout>
</android.support.design.widget.CoordinatorLayout>
I hope it helps you
This is not possible till you are using BottomSheetDialogFragment
. BottomSheetDialogFragment
is a dialog and as behaviour of every dialog, it does not allow user interception on any view behind the dialog, although that is visible to user.
So to achieve this you need to use Fragment
instead of BottomSheetDialogFragment
. And yes it will require lot of code changes :) and you have to live without BottomSheetDialogFragment
if you want to intercept views behind.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With