Skip to content

Commit 7453280

Browse files
jamesacklinm-bert
andauthored
[Android | Web] Disable pointer events on hidden Swipeable actions container (#4192)
## Description The left/right action containers in `ReanimatedSwipeable` are absolute-fill overlays that animate to `opacity: 0` when not revealed. On Android, an opacity-0 view still receives touches, so the hidden side stays on top in z-order and swallows taps that should reach the visible side's actions (or the row content itself). A common repro is a quick-action button exposed by a swipe: the button visibly responds to press feedback but the `onPress` never fires because the opposite-side container intercepts it. This adds a matching `pointerEvents` toggle to `leftActionAnimation` and `rightActionAnimation`, so each container becomes `'none'` alongside its opacity going to 0, and switches back to `'auto'` once revealed. iOS and web were not affected by the original bug, but the toggle is harmless on those platforms (an opacity-0 view there is already non-interactive). Fixes #3223. ## Test plan - Carried as a local patch against `react-native-gesture-handler@2.28.0` in our app for the last few weeks. Before the patch, Android taps on a swipe-revealed action were dropped intermittently; after the patch, every tap fires on the first try. iOS behavior was unchanged. - Manual repro for reviewers: in `apps/common-app`, open a `Swipeable` example, swipe a row to reveal an action, and tap the action on Android — the action should fire on the first tap. --------- Co-authored-by: Michał <michal.bert@swmansion.com> Co-authored-by: Michał Bert <63123542+m-bert@users.noreply.github.com>
1 parent 50cb5a6 commit 7453280

1 file changed

Lines changed: 8 additions & 0 deletions

File tree

packages/react-native-gesture-handler/src/components/ReanimatedSwipeable/ReanimatedSwipeable.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,10 @@ const Swipeable = (props: SwipeableProps) => {
393393
const leftActionAnimation = useAnimatedStyle(() => {
394394
return {
395395
opacity: showLeftProgress.value === 0 ? 0 : 1,
396+
// Both action containers use `absoluteFill` and overlap, so the
397+
// inactive one must not intercept touches meant for the visible
398+
// actions.
399+
pointerEvents: showLeftProgress.value === 0 ? 'none' : 'auto',
396400
};
397401
});
398402

@@ -423,6 +427,10 @@ const Swipeable = (props: SwipeableProps) => {
423427
const rightActionAnimation = useAnimatedStyle(() => {
424428
return {
425429
opacity: showRightProgress.value === 0 ? 0 : 1,
430+
// Both action containers use `absoluteFill` and overlap, so the
431+
// inactive one must not intercept touches meant for the visible
432+
// actions.
433+
pointerEvents: showRightProgress.value === 0 ? 'none' : 'auto',
426434
};
427435
});
428436

0 commit comments

Comments
 (0)