Material-components-android: [BottomSheetBehavior] State is incorrect if updated during settling animation

Created on 10 Aug 2019  路  9Comments  路  Source: material-components/material-components-android

Description:

BottomSheetBehavior#state is not updated correctly if it was updated during the BottomSheetBehavior.SETTLING state. BottomSheetCallback$onStateChanged is not called with the correct value either.

Visually, the sheet is in the proper state.

Expected behavior:

BottomSheetBehavior#state should match its visual state and BottomSheetCallback#onStateChanged should be called with the latest state change.

Source code:

Sample project: BottomSheetDemo.zip

Snippet to reproduce bug:

class BottomSheetView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0, defStyleRes: Int = 0) : FrameLayout(context, attrs, defStyleAttr, defStyleRes), CoordinatorLayout.AttachedBehavior {

    private val bottomSheetBehavior = BottomSheetBehavior<BottomSheetView>()

    init {
        // Initialize sheet to be hidden and set callback for when the state changes
        bottomSheetBehavior.isHideable = true
        bottomSheetBehavior.setBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
            override fun onSlide(p0: View, p1: Float) = Unit

            override fun onStateChanged(p0: View, p1: Int) {
                println("state changed $p1")
            }

        })
        updateState(BottomSheetBehavior.STATE_HIDDEN)
    }

    override fun onAttachedToWindow() {
        super.onAttachedToWindow()

        // Update state to be expanded (from hidden)
        postDelayed({
            updateState(BottomSheetBehavior.STATE_EXPANDED)
            // Update state to be hidden (from expanded during the settling animation)
            postDelayed({
                updateState(BottomSheetBehavior.STATE_HIDDEN)
                // Query the state of the sheet after animation completes
                postDelayed({
                    println("query state ${bottomSheetBehavior.state}")
                }, 1000)
            }, 300)
        }, 3000)
    }

    private fun updateState(state: Int) {
        println("update state to $state")
        bottomSheetBehavior.state = state
    }

    override fun getBehavior(): CoordinatorLayout.Behavior<BottomSheetView> = bottomSheetBehavior
}

On 1.1.0-alpha03 and newer versions (including 1.1.0-alpha09), the above outputs:

update state to 5
update state to 3
state changed 2
update state to 5
state changed 3
query state 3

On 1.0.0, the above outputs:

update state to 5
update state to 3
state changed 2
update state to 5
state changed 3
state changed 5
query state 5

The sheet's end state should be HIDDEN (5), but it returns EXPANDED (3).

Android API version: Reproducible on API 21 (Lollipop) and 29 (Q Beta)

Material Library version: 1.1.0-alpha09

Device: Nexus 5X emulator and Pixel 3

P1 bug

Most helpful comment

I can still observe incorrect behavior with material-components version 1.2.0.
The state change seems to be ignored when changing the state to BottomSheetBehavior.STATE_EXPANDED while the bottom sheet is currently settling.

The following workaround seems to solve the issue:

  private fun expandBottomSheet() {
+   if (bottomSheetBehavior.state == BottomSheetBehavior.STATE_SETTLING) {
+       // workaround for https://github.com/material-components/material-components-android/issues/516
+       handler.removeCallbacksAndMessages(null)
+       handler.postDelayed({ expandBottomSheet() }, 10)
+   } else {
        bottomSheetBehavior.state = BottomSheetBehavior.STATE_EXPANDED
+   }
  }

All 9 comments

I'm observing same behavior as well

I notice this behavior as well.

Seeing the same bug here as well

Thanks for reporting this! We're actively working on a fix for this issue now

Thanks @melaniegoetz

Hi @melaniegoetz, just checking in if you have an expected timeline for this fix. Thanks.

Hi there! The fix was submitted and synced out in (e057829) and will be included in the next alpha release

Gracias @melaniegoetz, appreciate your help here!

I can still observe incorrect behavior with material-components version 1.2.0.
The state change seems to be ignored when changing the state to BottomSheetBehavior.STATE_EXPANDED while the bottom sheet is currently settling.

The following workaround seems to solve the issue:

  private fun expandBottomSheet() {
+   if (bottomSheetBehavior.state == BottomSheetBehavior.STATE_SETTLING) {
+       // workaround for https://github.com/material-components/material-components-android/issues/516
+       handler.removeCallbacksAndMessages(null)
+       handler.postDelayed({ expandBottomSheet() }, 10)
+   } else {
        bottomSheetBehavior.state = BottomSheetBehavior.STATE_EXPANDED
+   }
  }
Was this page helpful?
0 / 5 - 0 ratings

Related issues

KelvinPac picture KelvinPac  路  3Comments

magnusfernandes picture magnusfernandes  路  3Comments

zkovar picture zkovar  路  3Comments

Sanusy picture Sanusy  路  3Comments

gabrielemariotti picture gabrielemariotti  路  3Comments