diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index 3452807bcdeb517aeff9d7f2abc53fddc7091d16..2bd198af6bf123f14572d0db3e777b36e80dc47b 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -353,6 +353,21 @@ void FlutterPlatformViewsController::EnsureGLOverlayInitialized( _delayingRecognizer.get().state = UIGestureRecognizerStateEnded; } +// We want the intercepting view to consume the touches and not pass the touches up to the parent +// view. Make the touch event method not call super will not pass the touches up to the parent view. +// Hence we overide the touch event methods and do nothing. +- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event { +} + +- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event { +} + +- (void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event { +} + +- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event { +} + @end @implementation DelayingGestureRecognizer { @@ -395,6 +410,8 @@ void FlutterPlatformViewsController::EnsureGLOverlayInitialized( // So this is safe as when FlutterView is deallocated the reference to ForwardingGestureRecognizer // will go away. UIView* _flutterView; + // Counting the pointers that has started in one touch sequence. + NSInteger _currentTouchPointersCount; } - (instancetype)initWithTarget:(id)target flutterView:(UIView*)flutterView { @@ -402,12 +419,15 @@ void FlutterPlatformViewsController::EnsureGLOverlayInitialized( if (self) { self.delegate = self; _flutterView = flutterView; + _currentTouchPointersCount = 0; } return self; } - (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event { [_flutterView touchesBegan:touches withEvent:event]; + _currentTouchPointersCount += touches.count; + [_flutterView touchesBegan:touches withEvent:event]; } - (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event { @@ -416,11 +436,19 @@ void FlutterPlatformViewsController::EnsureGLOverlayInitialized( - (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event { [_flutterView touchesEnded:touches withEvent:event]; - self.state = UIGestureRecognizerStateFailed; + _currentTouchPointersCount -= touches.count; + // Touches in one touch sequence are sent to the touchesEnded method separately if different + // fingers stop touching the screen at different time. So one touchesEnded method triggering does + // not necessarially mean the touch sequence has ended. We Only set the state to + // UIGestureRecognizerStateFailed when all the touches in the current touch sequence is ended. + if (_currentTouchPointersCount == 0) { + self.state = UIGestureRecognizerStateFailed; + } } - (void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event { [_flutterView touchesCancelled:touches withEvent:event]; + _currentTouchPointersCount = 0; self.state = UIGestureRecognizerStateFailed; }