Flutter iOS Embedder
FlutterTouchInterceptingView Class Reference

#import <FlutterPlatformViews_Internal.h>

Inheritance diagram for FlutterTouchInterceptingView:

Instance Methods

(instancetype) - initWithEmbeddedView:platformViewsController:gestureRecognizersBlockingPolicy:
 
(void) - releaseGesture
 
(void) - blockGesture
 
(UIView *) - embeddedView
 
(id) - accessibilityContainer
 

Properties

id flutterAccessibilityContainer
 
FlutterPlatformViewGestureRecognizersBlockingPolicy blockingPolicy
 

Detailed Description

Definition at line 523 of file FlutterPlatformViews.mm.

Method Documentation

◆ accessibilityContainer

- (id) accessibilityContainer

Provided by category FlutterTouchInterceptingView(Tests).

◆ blockGesture

- (void) blockGesture

Definition at line 520 of file FlutterPlatformViews.mm.

642  {
643  switch (_blockingPolicy) {
645  // No-op. Handled by hit test.
646  break;
648  // We block all other gesture recognizers immediately in this policy.
649  self.delayingRecognizer.state = UIGestureRecognizerStateEnded;
650 
651  // On iOS 18.2, WKWebView's internal recognizer likely caches the old state of its blocking
652  // recognizers (i.e. delaying recognizer), resulting in non-tappable links. See
653  // https://github.com/flutter/flutter/issues/158961. Removing and adding back the delaying
654  // recognizer solves the problem, possibly because UIKit notifies all the recognizers related
655  // to (blocking or blocked by) this recognizer. It is not possible to inject this workaround
656  // from the web view plugin level. Right now we only observe this issue for
657  // FlutterPlatformViewGestureRecognizersBlockingPolicyEager, but we should try it if a similar
658  // issue arises for the other policy.
659  if (@available(iOS 26.4, *)) {
660  // Skip workaround as this non-tappable web view bug has been fixed on iOS 26.4.
661  // See: https://github.com/WebKit/WebKit/pull/57358.
662  } else if (@available(iOS 26.0, *)) {
663  // This performs a nested DFS, with the outer one searching for any web view, and the inner
664  // one searching for a TouchEventsGestureRecognizer inside the web view. Once found, disable
665  // and immediately reenable it to reset its state.
666  // TODO(hellohuanlin): remove this flag after it is battle tested.
667  NSNumber* isWorkaroundDisabled =
668  [[NSBundle mainBundle] objectForInfoDictionaryKey:@"FLTDisableWebViewGestureReset"];
669  if (!isWorkaroundDisabled.boolValue) {
670  [self searchAndFixWebView:self.embeddedView];
671  }
672  } else if (@available(iOS 18.2, *)) {
673  // The 1P web view plugin provides a WKWebView itself as the platform view. However, some 3P
674  // plugins provide wrappers of WKWebView instead, and AdMob banner has a WKWebView at
675  // depth 7. So we perform DFS to search the view hierarchy.
676  if ([self containsWebView:self.embeddedView]) {
677  [self removeGestureRecognizer:self.delayingRecognizer];
678  [self addGestureRecognizer:self.delayingRecognizer];
679  }
680  }
681 
682  break;
684  if (self.delayingRecognizer.touchedEndedWithoutBlocking) {
685  // If touchesEnded of the `DelayingGesureRecognizer` has been already invoked,
686  // we want to set the state of the `DelayingGesureRecognizer` to
687  // `UIGestureRecognizerStateEnded` as soon as possible.
688  self.delayingRecognizer.state = UIGestureRecognizerStateEnded;
689  } else {
690  // If touchesEnded of the `DelayingGesureRecognizer` has not been invoked,
691  // We will set a flag to notify the `DelayingGesureRecognizer` to set the state to
692  // `UIGestureRecognizerStateEnded` when touchesEnded is called.
693  self.delayingRecognizer.shouldEndInNextTouchesEnded = YES;
694  }
695  break;
696  default:
697  break;
698  }
699 }
@ FlutterPlatformViewGestureRecognizersBlockingPolicyEager
@ FlutterPlatformViewGestureRecognizersBlockingPolicyWaitUntilTouchesEnded
@ FlutterPlatformViewGestureRecognizersBlockingPolicyDoNotBlockGesture

◆ embeddedView

- (UIView*) embeddedView

◆ initWithEmbeddedView:platformViewsController:gestureRecognizersBlockingPolicy:

- (instancetype) initWithEmbeddedView: (UIView*)  embeddedView
platformViewsController: (FlutterPlatformViewsController*)  platformViewsController
gestureRecognizersBlockingPolicy: (FlutterPlatformViewGestureRecognizersBlockingPolicy blockingPolicy 

Definition at line 520 of file FlutterPlatformViews.mm.

524  :(UIView*)embeddedView
525  platformViewsController:(FlutterPlatformViewsController*)platformViewsController
526  gestureRecognizersBlockingPolicy:
528  self = [super initWithFrame:embeddedView.frame];
529  if (self) {
530  self.multipleTouchEnabled = YES;
531  _embeddedView = embeddedView;
532  _platformViewsController = platformViewsController;
533  _flutterViewController = platformViewsController.flutterViewController;
534  embeddedView.autoresizingMask =
535  (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
536 
537  [self addSubview:embeddedView];
538 
539  ForwardingGestureRecognizer* forwardingRecognizer =
540  [[ForwardingGestureRecognizer alloc] initWithTarget:self
541  platformViewsController:platformViewsController];
542 
543  _delayingRecognizer =
544  [[FlutterDelayingGestureRecognizer alloc] initWithTarget:self
545  action:nil
546  forwardingRecognizer:forwardingRecognizer];
547  _blockingPolicy = blockingPolicy;
548 
549  // For hit test, don't block gestures using delaying recognizer. However, we still
550  // forward touches so Flutter can process it in its gesture arena (e.g. dismiss a
551  // drop-down menu when tapping outside of the menu but inside the platform view).
553  [self addGestureRecognizer:_delayingRecognizer];
554  }
555  [self addGestureRecognizer:forwardingRecognizer];
556  }
557  return self;
558 }
UIViewController< FlutterViewResponder > * _flutterViewController
FlutterPlatformViewGestureRecognizersBlockingPolicy
FlutterPlatformViewGestureRecognizersBlockingPolicy blockingPolicy
UIViewController< FlutterViewResponder > *_Nullable flutterViewController
The flutter view controller.

◆ releaseGesture

- (void) releaseGesture

Definition at line 520 of file FlutterPlatformViews.mm.

574  {
575  self.delayingRecognizer.state = UIGestureRecognizerStateFailed;
576 }

Property Documentation

◆ blockingPolicy

- (FlutterPlatformViewGestureRecognizersBlockingPolicy) blockingPolicy
readnonatomicassign

Definition at line 159 of file FlutterPlatformViews_Internal.h.

◆ flutterAccessibilityContainer

- (id) flutterAccessibilityContainer
readwritenonatomicretain

Definition at line 158 of file FlutterPlatformViews_Internal.h.


The documentation for this class was generated from the following files: