Reputation: 468
I have a BottomSheetDialogFragment
. But even the slightest downward swipe dismisses the Dialog.
I do not want to make it static and remove the swipe down to dismiss behaviour. I want to be able to change the sensitivity, if the swipe is x
pixels downwards, then dismiss
Upvotes: 3
Views: 1922
Reputation: 2528
I'm going to assume that like me, you had a NestedScrollView
in your bottom sheet (this is the only thing that caused the behavior you described to happen for me).
My solution was as follows:
/** Convenience function to fix https://github.com/material-components/material-components-android/issues/1055 */
private fun NestedScrollView.fixNestedScrolling(dialog: BottomSheetDialog) {
fun updateScrollView(scrollY: Int) {
val wasNestedScrollingEnabled = isNestedScrollingEnabled
isNestedScrollingEnabled = scrollY > 0
if (wasNestedScrollingEnabled != isNestedScrollingEnabled) {
// If property has changed, we need to requestLayout for it to apply to swipe gestures.
dialog.findViewById<View>(R.id.design_bottom_sheet)?.requestLayout()
}
}
setOnScrollChangeListener { _, _, scrollY, _, _ -> updateScrollView(scrollY) }
// Fire off initial update
updateScrollView(0)
}
The NestedScrollView
still works correctly, and once scrollY == 0 (i.e. we're at the top), nested scrolling is disabled so the BottomSheetBehavior
uses the (much more natural) calculations that it usually does before initiating a dismiss.
Upvotes: 0
Reputation: 1741
The answer of ChiChung Luk almost acceptable, but I have tried it with com.google.android.material:material:1.2.1
library and it didn't work as expected. First of all slideOffset
changes from 1 to -1, and not from 0 to -1. The second issue was that even when we set mBehavior.setState(STATE_EXPANDED)
in onStateChanged
, the system any way sets the state to STATE_HIDDEN
after the bottom sheet is expanded, from onStopNestedScroll > startSettlingAnimation
. So there should be a flag that disallow hide before bottom sheet is not expanded.
Solution:
bottomSheetBehavior.addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
val dismissOffset: Float = -0.2f // when less value then wider should be swipe gesture to dismiss
private var currOffset: Float = 1f // from 1 to -1
private var dismissAllowed: Boolean = true
override fun onStateChanged(
bottomSheet: View, @BottomSheetBehavior.State newState: Int
) {
if (newState == BottomSheetBehavior.STATE_SETTLING) {
if (currOffset > dismissOffset) {
dismissAllowed = false
bottomSheetBehavior.state = BottomSheetBehavior.STATE_EXPANDED
} else {
bottomSheetBehavior.state = BottomSheetBehavior.STATE_HIDDEN
}
} else if (newState == BottomSheetBehavior.STATE_EXPANDED) {
dismissAllowed = true
} else if (newState == BottomSheetBehavior.STATE_HIDDEN) {
if (dismissAllowed) {
dialog.cancel()
}
}
}
override fun onSlide(bottomSheet: View, slideOffset: Float) {
currOffset = slideOffset
}
})
Upvotes: 0
Reputation: 581
use BottomSheetBehavior
this will get the behavior for your BottomSheetDialogFragment view
var mBehavior: BottomSheetBehavior<*> = BottomSheetBehavior.from([your view reference])
then you can setup like this
val dismissOffset: Float = [-1..0] // 0 is the starting position. -1 is hidden. -0.5 is middle
var offset: Float? = null
mBehavior.setBottomSheetCallback(object : BottomSheetCallback() {
override fun onStateChanged(bottomSheet: View, newState: Int) {
if (newState == BottomSheetBehavior.STATE_SETTLING) {
if (offset!! > dismissOffset) {
mBehavior.setState(BottomSheetBehavior.STATE_EXPANDED)
} else {
mBehavior.setState(BottomSheetBehavior.STATE_HIDDEN)
}
}
}
override fun onSlide(bottomSheet: View, slideOffset: Float) {
offset = slideOffset
}
})
Upvotes: 2