BottomSheetBehaviour setstate without animation

Viewed 5076

I have tried the new BottomSheetBehaviour with design library 23.0.2 but i think it too limited. When I change state with setState() method, the bottomsheet use ad animation to move to the new state.

How can I change state immediately, without animation? I don't see a public method to do that.

3 Answers

If you want to remove the show/close animation you can use dialog.window?.setWindowAnimations(-1). For instance:

class MyDialog(): BottomSheetDialogFragment() {

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        val dialog = super.onCreateDialog(savedInstanceState)

        dialog.window?.setDimAmount(0f) // for removing the dimm
        dialog.window?.setWindowAnimations(-1) // for removing the animation

        return dialog
    }
}

If you really need it, then you can resort to reflection:

  fun BottomSheetBehavior.getViewDragHelper(): ViewDragHelper? = BottomSheetBehavior::class.java
    .getDeclaredField("viewDragHelper")
    .apply { isAccessible = true }
    .let { field -> field.get(this) as? ViewDragHelper? }

  fun ViewDragHelper.getScroller(): OverScroller? = ViewDragHelper::class.java
    .getDeclaredField("mScroller")
    .apply { isAccessible = true }
    .let { field -> field.get(this) as? OverScroller? }

Then you can use these extension methods when the state changes:

  bottomSheetBehavior.setBottomSheetCallback(object : BottomSheetCallback() {
      override fun onSlide(view: View, offset: Float) {}

      override fun onStateChanged(view: View, state: Int) {
        if (state == STATE_SETTLING) {
           try { 
              bottomSheetBehavior.getViewDragHelper()?.getScroller()?.abortAnimation()
           } catch(e: Throwable) {}
        }
      }
    })

I will add that the code is not perfect, getting fields every time the state changes is not efficient, and this is done for the sake of simplicity.

Related