fix(android): ignore scrim taps once the sheet is closing - #80
Conversation
A scrim tap dismisses the sheet by snapping to the closed detent, but the Android handler never checks whether that detent is already the target. The scrim stays visible while the close animates, so every further tap runs snapToIndex again: it emits another onIndexChange and cancels the running spring, restarting the close from zero velocity. Tapping the scrim three times reports three index changes for one dismissal and stalls the sheet. iOS already guards this in handleScrimPress with targetIndex != closedIndex. Apply the same guard on Android.
8e7380d to
5939dc1
Compare
|
Fixed the unit test that failed on the previous CI run. Both cases asserted The tests now assert only the synchronous Verified locally with |
Summary
On Android, tapping the scrim of a modal sheet that is already animating to
its closed detent starts the dismissal over again.
onTouchEventsnaps toscrimDismissIndexon every scrim release, withoutchecking whether that detent is already
targetIndex:https://github.com/software-mansion-labs/react-native-bottom-sheet/blob/249b2cf/android/src/main/java/com/swmansion/reactnativebottomsheet/BottomSheetHostView.kt#L1185-L1194
The scrim stays visible for the whole close animation:
updateScrimonlyforces it hidden once the sheet is settled at the closed detent
(
isTargetingClosedDetent && activeAnimation == null && !isPanning), soisScrimVisible()is still true mid-close and every further tap is treatedas a fresh dismissal. Each one calls
snapToIndex(closeIndex, 0f), whichemits
onIndexChangeand cancels the in-flight spring to start a new onefrom zero velocity, so the sheet also loses the momentum it had.
iOS does not have this:
handleScrimPressbails when the closed detent isalready the target.
https://github.com/software-mansion-labs/react-native-bottom-sheet/blob/249b2cf/ios/BottomSheetHostingView.swift#L717-L728
Fix
Add the same
closeIndex != targetIndexguard to the Android handler.A settled closed sheet is unaffected, because its scrim is already hidden and
shouldDismissis false there.Repro
Modal sheet with
detents={[0, 300]},index={1}and a scrim, tapping thescrim three times in quick succession:
onIndexChangeonSettle0,0,0000Test plan
android/src/test/.../BottomSheetViewScrimDismissTest.ktcovers boththe single tap (still dismisses) and the repeated taps (one index change).
expected:<[0]> but was:<[0, 0, 0]>while the single-tap test still passes,then restored it and confirmed the whole
test:android:unitsuite is green.bun run lint,bun run typecheck,ktfmt --google-style.