From 0212fd385cd991ef37c0efe0c1210948fd4d36fc Mon Sep 17 00:00:00 2001 From: Julian Rex Date: Thu, 24 May 2018 01:01:20 -0400 Subject: [ios] Provide custom hit test for callout views (#11939) --- platform/ios/CHANGELOG.md | 1 + platform/ios/vendor/SMCalloutView/SMCalloutView.m | 38 +++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md index f34b15face..7c8181a65a 100644 --- a/platform/ios/CHANGELOG.md +++ b/platform/ios/CHANGELOG.md @@ -18,6 +18,7 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT * Adjusted when and how the camera transition update and finish callbacks are called, fixing recursion bugs. ([#11614](https://github.com/mapbox/mapbox-gl-native/pull/11614)) * Improved application launch performance. * Fixed an issue preventing nested key path expressions get parsed accordingly to the spec. ([#11959](https://github.com/mapbox/mapbox-gl-native/pull/11959)) +* Added custom `-hitTest:withEvent:` to `MGLSMCalloutView` to avoid registering taps in transparent areas of the standard annotation callout. ([#11939](https://github.com/mapbox/mapbox-gl-native/pull/11939)) ## 4.0.1 - May 14, 2018 diff --git a/platform/ios/vendor/SMCalloutView/SMCalloutView.m b/platform/ios/vendor/SMCalloutView/SMCalloutView.m index a0049a3e2d..7f987c3355 100755 --- a/platform/ios/vendor/SMCalloutView/SMCalloutView.m +++ b/platform/ios/vendor/SMCalloutView/SMCalloutView.m @@ -62,6 +62,26 @@ NSTimeInterval const kMGLSMCalloutViewRepositionDelayForUIScrollView = 1.0/3.0; return self; } +- (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; +} + - (BOOL)supportsHighlighting { if (![self.delegate respondsToSelector:@selector(calloutViewClicked:)]) return NO; @@ -738,6 +758,24 @@ static UIImage *blackArrowImage = nil, *whiteArrowImage = nil, *grayArrowImage = return layer; } +- (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; +} + @end @implementation MGLSMCalloutBackgroundView -- cgit v1.2.1