Funny Devs
Funny Devs

Reputation: 305

BottomSheetBehaviour setstate without animation

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.

Upvotes: 27

Views: 6368

Answers (3)

Kuvonchbek Yakubov
Kuvonchbek Yakubov

Reputation: 749

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
    }
}

Upvotes: 1

maXp
maXp

Reputation: 1468

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.

Upvotes: 0

Viacheslav
Viacheslav

Reputation: 5593

Unfortunately it looks like you can't. Invocation of BottomSheetBehavior's setState ends with synchronous or asynchronous call of startSettlingAnimation(child, state). And there is no way to override these methods behavior cause setState is final and startSettlingAnimation has package visible modifier. Check the sources for more information.

I have problems with the same, but in a bit different way - my UI state changes setHideable to false before that settling animation invokes, so I'm getting IllegalStateException there. I will consider usage of BottomSheetCallback to manage this properly.

Upvotes: 6

Related Questions