Vedant
Vedant

Reputation: 468

How can I change the sensitivity of Dismiss Behaviour of BottomSheetDialog

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

Answers (3)

Kane O'Riley
Kane O'Riley

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

Oleksandr Albul
Oleksandr Albul

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

Neo Luk
Neo Luk

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

Related Questions