Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions packages/react-native-gesture-handler/apple/RNGestureHandler.mm
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,16 @@ - (void)handleGesture:(UIGestureRecognizer *)recognizer

_state = [self recognizerState];

// When the state manager activates a handler it dispatches ACTIVE itself and sets the recognizer's
// state to Began so that UIKit keeps driving it. UIKit delivers the action for that
// programmatic transition asynchronously, so this method runs later with the recognizer in Began
// while ACTIVE has already been sent. `sendEventsInState:` drops that stale event, but by then
// `_state` (which touch events report) would have been overwritten. Keep the handler active instead.
if (!fromReset && _state == RNGestureHandlerStateBegan && _lastState == RNGestureHandlerStateActive) {
_state = RNGestureHandlerStateActive;
return;
}

// From iOS 26.0 when recognizers are reset, their state is also changed to UIGestureRecognizerStatePossible.
// This means that our logic that relies on sending events in `reset` methods doesn't work properly. The bug that
// `onFinalize` was not send after `onBegin` happened because both recognizer states, `Began` and `Possible`, are
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -245,12 +245,18 @@ - (void)setGestureStateSync:(int)state forHandler:(int)handlerTag
} else if (state == 3) { // CANCELLED
handler.recognizer.state = RNGHGestureRecognizerStateCancelled;
} else if (state == 4) { // ACTIVE
// We don't allow activation of gestures which haven't received any touches
if (handler.lastState == RNGestureHandlerStateUndetermined) {
if (handler.lastState == RNGestureHandlerStateUndetermined && handler.pointerTracker.trackedPointersCount > 0) {
[handler handleGesture:handler.recognizer inState:RNGestureHandlerStateBegan fromManualStateChange:YES];
}

if (handler.lastState != RNGestureHandlerStateBegan) {
return;
}
Comment thread
m-bert marked this conversation as resolved.

[handler stopActivationBlocker];
handler.recognizer.state = RNGHGestureRecognizerStateBegan;
// Don't wait for the next touch move to report ACTIVE.
[handler handleGesture:handler.recognizer inState:RNGestureHandlerStateActive fromManualStateChange:YES];
} else if (state == 5) { // ENDED
handler.recognizer.state = RNGHGestureRecognizerStateEnded;
}
Expand Down
Loading