From 01e2f78ccba221290b0e4ae89180477b552dd9b8 Mon Sep 17 00:00:00 2001 From: Julian Rex Date: Fri, 11 May 2018 11:48:35 -0400 Subject: Provide custom hit test for callout views to avoid selecting callout when tapping in blank space. Refs #11875 --- platform/ios/vendor/SMCalloutView/SMCalloutView.m | 44 +++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/platform/ios/vendor/SMCalloutView/SMCalloutView.m b/platform/ios/vendor/SMCalloutView/SMCalloutView.m index a0049a3e2d..81517c2b12 100755 --- a/platform/ios/vendor/SMCalloutView/SMCalloutView.m +++ b/platform/ios/vendor/SMCalloutView/SMCalloutView.m @@ -28,6 +28,8 @@ #define TOP_ANCHOR_MARGIN 13 // all the above measurements assume a bottom anchor! if we're pointing "up" we'll need to add this top margin to everything. #define COMFORTABLE_MARGIN 10 // when we try to reposition content to be visible, we'll consider this margin around your target rect +#define CHECK_CALLOUT_SHAPE_FOR_HIT_TEST + NSTimeInterval const kMGLSMCalloutViewRepositionDelayForUIScrollView = 1.0/3.0; @interface MGLSMCalloutView () @@ -62,6 +64,28 @@ NSTimeInterval const kMGLSMCalloutViewRepositionDelayForUIScrollView = 1.0/3.0; return self; } +#ifdef CHECK_CALLOUT_SHAPE_FOR_HIT_TEST +- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event { + UIView* hitView = [super hitTest:point withEvent:event]; + + // If we tapped on our container (i.e. the UIButton), then ask the background + // view if the point is "inside". MGLSMCalloutMaskedBackgroundView provides a + // custom implementation that checks against the main callout and the down arrow. + // This avoids taps in "blank" space being detected + + if (hitView == self.containerView) { + // Ideally we'd use the background mask to determine whether a tap point + // is valid, but that's overkill in this situation + CGPoint backgroundPoint = [self convertPoint:point toView:self.backgroundView]; + if (![self.backgroundView pointInside:backgroundPoint withEvent:event]) { + return nil; + } + } + + return hitView; +} +#endif + - (BOOL)supportsHighlighting { if (![self.delegate respondsToSelector:@selector(calloutViewClicked:)]) return NO; @@ -738,6 +762,26 @@ static UIImage *blackArrowImage = nil, *whiteArrowImage = nil, *grayArrowImage = return layer; } +#ifdef CHECK_CALLOUT_SHAPE_FOR_HIT_TEST +- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event { + + // Only interested in providing a custom pointInside for touches. + if (event.type != UIEventTypeTouches) { + return [super pointInside:point withEvent:event]; + } + + NSArray *views = @[self.containerView, self.arrowView]; + for (UIView *view in views) { + CGPoint viewPoint = [self convertPoint:point toView:view]; + if (CGRectContainsPoint(view.bounds, viewPoint)) { + return YES; + } + } + + return NO; +} +#endif + @end @implementation MGLSMCalloutBackgroundView -- cgit v1.2.1