Fixes an Android bug where a closed BottomSheet with a backdrop can block all touch events on the underlying screen after a cold start. - #2706
Conversation
|
This PR is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 10 days. |
|
Any update when this PR will be merged? |
|
Yes, also wondering when this will merge. This fixes the issue for me on Android 15 and in my case the issue arises not just on cold starts but consistently (even when backgrounding the app) and cannot be recovered from. |
|
I ran into this exact issue in my own project — the closed BottomSheet with a backdrop was blocking all touch events after a cold start. |
|
@gorhom following up on this -there is still demand to merge it. This PR is still mergeable against master (one file, no API change). Linked issue #2680 was closed as stale, not as fixed, and the bug is still present in 5.2.14. Recent comments here confirm it on Android 11–15 (Samsung, Xiaomi, Pixel); in at least one report it is consistent, not only on cold start, and people are patching locally to ship. Related #2342 (Math.floor on animatedIndex) covers the same floating-point miss, but rounding the index too aggressively lets taps go through the backdrop while the sheet is still opening. The epsilon check here (index <= disappearsOnIndex + 0.01) treats near-closed values like -0.999… as closed without changing mid-animation behavior. Happy to adjust if you want a different threshold or extra coverage. Otherwise this looks ready to land. |
Fixes an Android bug where a closed BottomSheet with a backdrop can block all touch events on the underlying screen after a cold start.
Closes #2680
Problem
When a screen mounts a closed bottom sheet (index={-1}) with a BottomSheetBackdrop, some Android devices stop receiving scroll and button presses on the content behind the sheet. The UI renders correctly, but touches appear to be swallowed. Backgrounding the app and returning restores interaction without navigating away.
Reported on devices including Samsung (Android 14) and Xiaomi (Android 11).
Root cause
Two independent issues in BottomSheetBackdrop:
Mount race condition
pointerEvents was always initialized to 'auto' when enableTouchThrough is false. useAnimatedReaction can fire before the mount useEffect sets isMounted.current = true. Because handleContainerTouchability only updates state when mounted, that first update is silently skipped and the invisible backdrop keeps intercepting touches.
Floating-point animatedIndex
On some devices, animatedIndex settles at -0.999… instead of exactly -1. With disappearsOnIndex={-1}, the check animatedIndex.value <= disappearsOnIndex evaluates to false, so pointerEvents never switches to 'none'.
Solution
Derive the initial pointerEvents value from the current animatedIndex instead of defaulting to 'auto'
Sync pointerEvents on mount to recover from the race where the animated reaction fires before the component is mounted
Use an epsilon-based closed-state check (index <= disappearsOnIndex + 0.01) so near-closed values like -0.9999 are treated as closed without affecting partially open positions during animations
How to reproduce (before fix)
Use @gorhom/bottom-sheet@5.2.14
Render a screen with scrollable content and a closed bottom sheet (index={-1})
Add a backdrop with appearsOnIndex={0} and disappearsOnIndex={-1}
Cold start on an affected Android device
Try scrolling or pressing buttons behind the sheet
Observe that touches are blocked until the app is backgrounded and resumed
<BottomSheet
ref={sheetRef}
index={-1}
enableDynamicSizing
enablePanDownToClose
backdropComponent={renderBackdrop}
...
Test plan
yarn typescript
passes
biome check
passes on the changed file
Cold-start repro on physical Android device (Samsung / Xiaomi class devices)
Verify backdrop still captures presses when the sheet is open
Verify
enableTouchThrough
behavior is unchanged
Verify opening/closing the sheet still works as expected
Risks / notes
The epsilon value (0.01) is intentionally small so mid-animation indices (e.g. -0.3) are not incorrectly treated as closed
This is a targeted change to BottomSheetBackdrop.tsx only; no API changes
Related community workaround was setting disappearsOnIndex={-0.5} — this fix addresses the underlying comparison issue without requiring consumers to change their config