diff options
author | Julian Rex <julian.rex@gmail.com> | 2018-02-12 16:37:21 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-02-12 16:37:21 -0500 |
commit | 9ee99c91bbf995302ead77a3f6fa22443f50a910 (patch) | |
tree | 1d23f40e4b327aa26606990cc217126db9bacc0e /platform/ios/src/MGLMapView.mm | |
parent | 560afaf1fb8f1cd20cef261da4992cd8a5478f88 (diff) | |
download | qtlocation-mapboxgl-9ee99c91bbf995302ead77a3f6fa22443f50a910.tar.gz |
[ios] Adds camera change delegate methods with reason parameter. (#11151)
Added missing notification handler for UIApplicationWillResignActiveNotification.
Diffstat (limited to 'platform/ios/src/MGLMapView.mm')
-rw-r--r-- | platform/ios/src/MGLMapView.mm | 178 |
1 files changed, 134 insertions, 44 deletions
diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index 0849cbd12f..f2141c3840 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -209,6 +209,8 @@ public: @property (nonatomic) UILongPressGestureRecognizer *quickZoom; @property (nonatomic) UIPanGestureRecognizer *twoFingerDrag; +@property (nonatomic) MGLCameraChangeReason cameraChangeReasonBitmask; + /// Mapping from reusable identifiers to annotation images. @property (nonatomic) NS_MUTABLE_DICTIONARY_OF(NSString *, MGLAnnotationImage *) *annotationImagesByIdentifier; @@ -502,10 +504,6 @@ public: _doubleTap.numberOfTapsRequired = 2; [self addGestureRecognizer:_doubleTap]; - _singleTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTapGesture:)]; - [_singleTapGestureRecognizer requireGestureRecognizerToFail:_doubleTap]; - _singleTapGestureRecognizer.delegate = self; - [self addGestureRecognizer:_singleTapGestureRecognizer]; _twoFingerDrag = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleTwoFingerDragGesture:)]; _twoFingerDrag.minimumNumberOfTouches = 2; @@ -530,16 +528,25 @@ public: [_quickZoom requireGestureRecognizerToFail:_doubleTap]; [self addGestureRecognizer:_quickZoom]; + _singleTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTapGesture:)]; + [_singleTapGestureRecognizer requireGestureRecognizerToFail:_doubleTap]; + _singleTapGestureRecognizer.delegate = self; + [_singleTapGestureRecognizer requireGestureRecognizerToFail:_quickZoom]; + [self addGestureRecognizer:_singleTapGestureRecognizer]; + // observe app activity // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(willTerminate) name:UIApplicationWillTerminateNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sleepGL:) name:UIApplicationDidEnterBackgroundNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(wakeGL:) name:UIApplicationWillEnterForegroundNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sleepGL:) name:UIApplicationWillResignActiveNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(wakeGL:) name:UIApplicationDidBecomeActiveNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didReceiveMemoryWarning) name:UIApplicationDidReceiveMemoryWarningNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deviceOrientationDidChange:) name:UIDeviceOrientationDidChangeNotification object:nil]; [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; + // set initial position // mbgl::CameraOptions options; @@ -547,6 +554,9 @@ public: mbgl::EdgeInsets padding = MGLEdgeInsetsFromNSEdgeInsets(self.contentInset); options.padding = padding; options.zoom = 0; + + _cameraChangeReasonBitmask = MGLCameraChangeReasonNone; + _mbglMap->jumpTo(options); _pendingLatitude = NAN; _pendingLongitude = NAN; @@ -1233,6 +1243,8 @@ public: - (void)handleCompassTapGesture:(__unused id)sender { + self.cameraChangeReasonBitmask |= MGLCameraChangeReasonResetNorth; + [self resetNorthAnimated:YES]; if (self.userTrackingMode == MGLUserTrackingModeFollowWithHeading || @@ -1255,6 +1267,7 @@ public: - (void)notifyGestureDidBegin { BOOL animated = NO; + [self cameraWillChangeAnimated:animated]; _mbglMap->setGestureInProgress(true); _changeDelimiterSuppressionDepth++; @@ -1278,6 +1291,23 @@ public: return _changeDelimiterSuppressionDepth > 0; } +- (BOOL)_shouldChangeFromCamera:(nonnull MGLMapCamera *)oldCamera toCamera:(nonnull MGLMapCamera *)newCamera +{ + // Check delegates first + if ([self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:reason:)]) + { + return [self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:newCamera reason:self.cameraChangeReasonBitmask]; + } + else if ([self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)]) + { + return [self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:newCamera]; + } + else + { + return YES; + } +} + - (void)handlePanGesture:(UIPanGestureRecognizer *)pan { if ( ! self.isScrollEnabled) return; @@ -1285,7 +1315,9 @@ public: _mbglMap->cancelTransitions(); MGLMapCamera *oldCamera = self.camera; - + + self.cameraChangeReasonBitmask |= MGLCameraChangeReasonGesturePan; + if (pan.state == UIGestureRecognizerStateBegan) { [self trackGestureEvent:MGLEventGesturePanStart forRecognizer:pan]; @@ -1299,9 +1331,8 @@ public: CGPoint delta = [pan translationInView:pan.view]; MGLMapCamera *toCamera = [self cameraByPanningWithTranslation:delta panGesture:pan]; - - if (![self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)] || - [self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:toCamera]) + + if ([self _shouldChangeFromCamera:oldCamera toCamera:toCamera]) { _mbglMap->moveBy({ delta.x, delta.y }); [pan setTranslation:CGPointZero inView:pan.view]; @@ -1323,9 +1354,8 @@ public: { CGPoint offset = CGPointMake(velocity.x * self.decelerationRate / 4, velocity.y * self.decelerationRate / 4); MGLMapCamera *toCamera = [self cameraByPanningWithTranslation:offset panGesture:pan]; - - if (![self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)] || - [self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:toCamera]) + + if ([self _shouldChangeFromCamera:oldCamera toCamera:toCamera]) { _mbglMap->moveBy({ offset.x, offset.y }, MGLDurationFromTimeInterval(self.decelerationRate)); } @@ -1356,6 +1386,8 @@ public: CGPoint centerPoint = [self anchorPointForGesture:pinch]; MGLMapCamera *oldCamera = self.camera; + self.cameraChangeReasonBitmask |= MGLCameraChangeReasonGesturePinch; + if (pinch.state == UIGestureRecognizerStateBegan) { [self trackGestureEvent:MGLEventGesturePinchStart forRecognizer:pinch]; @@ -1372,9 +1404,8 @@ public: // Calculates the final camera zoom, has no effect within current map camera. MGLMapCamera *toCamera = [self cameraByZoomingToZoomLevel:newZoom aroundAnchorPoint:centerPoint]; - - if (![self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)] || - [self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:toCamera]) + + if ([self _shouldChangeFromCamera:oldCamera toCamera:toCamera]) { _mbglMap->setZoom(newZoom, mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y }); // The gesture recognizer only reports the gesture’s current center @@ -1426,9 +1457,8 @@ public: // Calculates the final camera zoom, this has no effect within current map camera. double zoom = log2(newScale); MGLMapCamera *toCamera = [self cameraByZoomingToZoomLevel:zoom aroundAnchorPoint:centerPoint]; - - if ([self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)] - && ![self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:toCamera]) + + if ([self _shouldChangeFromCamera:oldCamera toCamera:toCamera]) { drift = NO; } else { @@ -1454,7 +1484,9 @@ public: CGPoint centerPoint = [self anchorPointForGesture:rotate]; MGLMapCamera *oldCamera = self.camera; - + + self.cameraChangeReasonBitmask |= MGLCameraChangeReasonGestureRotate; + if (rotate.state == UIGestureRecognizerStateBegan) { [self trackGestureEvent:MGLEventGestureRotateStart forRecognizer:rotate]; @@ -1481,9 +1513,8 @@ public: } MGLMapCamera *toCamera = [self cameraByRotatingToDirection:newDegrees aroundAnchorPoint:centerPoint]; - - if (![self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)] || - [self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:toCamera]) + + if ([self _shouldChangeFromCamera:oldCamera toCamera:toCamera]) { _mbglMap->setBearing(newDegrees, mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y }); } @@ -1501,9 +1532,8 @@ public: CGFloat newDegrees = MGLDegreesFromRadians(newRadians) * -1; MGLMapCamera *toCamera = [self cameraByRotatingToDirection:newDegrees aroundAnchorPoint:centerPoint]; - - if (![self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)] || - [self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:toCamera]) + + if ([self _shouldChangeFromCamera:oldCamera toCamera:toCamera]) { _mbglMap->setBearing(newDegrees, mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y }, MGLDurationFromTimeInterval(decelerationRate)); @@ -1548,6 +1578,7 @@ public: } [self deselectAnnotation:self.selectedAnnotation animated:YES]; UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nextElement); + return; } @@ -1558,7 +1589,7 @@ public: CGRect positionRect = [self positioningRectForAnnotation:annotation defaultCalloutPoint:calloutPoint]; [self selectAnnotation:annotation animated:YES calloutPositioningRect:positionRect]; } - else + else if (self.selectedAnnotation) { [self deselectAnnotation:self.selectedAnnotation animated:YES]; } @@ -1640,6 +1671,8 @@ public: if (doubleTap.state == UIGestureRecognizerStateEnded) { + self.cameraChangeReasonBitmask |= MGLCameraChangeReasonGestureZoomIn; + MGLMapCamera *oldCamera = self.camera; double newZoom = round(self.zoomLevel) + 1.0; @@ -1647,9 +1680,8 @@ public: CGPoint gesturePoint = [self anchorPointForGesture:doubleTap]; MGLMapCamera *toCamera = [self cameraByZoomingToZoomLevel:newZoom aroundAnchorPoint:gesturePoint]; - - if (![self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)] || - [self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:toCamera]) + + if ([self _shouldChangeFromCamera:oldCamera toCamera:toCamera]) { [self trackGestureEvent:MGLEventGestureDoubleTap forRecognizer:doubleTap]; @@ -1676,9 +1708,13 @@ public: _mbglMap->cancelTransitions(); + self.cameraChangeReasonBitmask |= MGLCameraChangeReasonGestureZoomOut; + if (twoFingerTap.state == UIGestureRecognizerStateBegan) { [self trackGestureEvent:MGLEventGestureTwoFingerSingleTap forRecognizer:twoFingerTap]; + + [self notifyGestureDidBegin]; } else if (twoFingerTap.state == UIGestureRecognizerStateEnded) { @@ -1689,9 +1725,8 @@ public: CGPoint gesturePoint = [self anchorPointForGesture:twoFingerTap]; MGLMapCamera *toCamera = [self cameraByZoomingToZoomLevel:newZoom aroundAnchorPoint:gesturePoint]; - - if (![self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)] || - [self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:toCamera]) + + if ([self _shouldChangeFromCamera:oldCamera toCamera:toCamera]) { mbgl::ScreenCoordinate center(gesturePoint.x, gesturePoint.y); _mbglMap->setZoom(newZoom, center, MGLDurationFromTimeInterval(MGLAnimationDuration)); @@ -1711,7 +1746,9 @@ public: if ( ! self.isZoomEnabled) return; _mbglMap->cancelTransitions(); - + + self.cameraChangeReasonBitmask |= MGLCameraChangeReasonGestureOneFingerZoom; + if (quickZoom.state == UIGestureRecognizerStateBegan) { [self trackGestureEvent:MGLEventGestureQuickZoom forRecognizer:quickZoom]; @@ -1734,9 +1771,8 @@ public: MGLMapCamera *oldCamera = self.camera; MGLMapCamera *toCamera = [self cameraByZoomingToZoomLevel:newZoom aroundAnchorPoint:centerPoint]; - - if (![self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)] || - [self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:toCamera]) + + if ([self _shouldChangeFromCamera:oldCamera toCamera:toCamera]) { _mbglMap->setZoom(newZoom, mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y }); } @@ -1756,6 +1792,8 @@ public: _mbglMap->cancelTransitions(); + self.cameraChangeReasonBitmask |= MGLCameraChangeReasonGestureTilt; + if (twoFingerDrag.state == UIGestureRecognizerStateBegan) { [self trackGestureEvent:MGLEventGesturePitchStart forRecognizer:twoFingerDrag]; @@ -1775,8 +1813,7 @@ public: MGLMapCamera *oldCamera = self.camera; MGLMapCamera *toCamera = [self cameraByTiltingToPitch:pitchNew]; - if (![self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)] || - [self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:toCamera]) + if ([self _shouldChangeFromCamera:oldCamera toCamera:toCamera]) { _mbglMap->setPitch(pitchNew, mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y }); } @@ -2852,6 +2889,8 @@ public: { self.userTrackingMode = MGLUserTrackingModeNone; + self.cameraChangeReasonBitmask |= MGLCameraChangeReasonProgrammatic; + [self _setCenterCoordinate:centerCoordinate edgePadding:self.contentInset zoomLevel:zoomLevel direction:direction duration:animated ? MGLAnimationDuration : 0 animationTimingFunction:nil completionHandler:completion]; } @@ -2901,6 +2940,9 @@ public: } _mbglMap->cancelTransitions(); + + self.cameraChangeReasonBitmask |= MGLCameraChangeReasonProgrammatic; + _mbglMap->easeTo(cameraOptions, animationOptions); } @@ -2924,6 +2966,8 @@ public: if (zoomLevel == self.zoomLevel) return; _mbglMap->cancelTransitions(); + self.cameraChangeReasonBitmask |= MGLCameraChangeReasonProgrammatic; + CGFloat duration = animated ? MGLAnimationDuration : 0; _mbglMap->setZoom(zoomLevel, @@ -3012,6 +3056,9 @@ public: - (void)setVisibleCoordinates:(const CLLocationCoordinate2D *)coordinates count:(NSUInteger)count edgePadding:(UIEdgeInsets)insets direction:(CLLocationDirection)direction duration:(NSTimeInterval)duration animationTimingFunction:(nullable CAMediaTimingFunction *)function completionHandler:(nullable void (^)(void))completion { self.userTrackingMode = MGLUserTrackingModeNone; + + self.cameraChangeReasonBitmask |= MGLCameraChangeReasonProgrammatic; + [self _setVisibleCoordinates:coordinates count:count edgePadding:insets direction:direction duration:duration animationTimingFunction:function completionHandler:completion]; } @@ -3061,6 +3108,9 @@ public: [self willChangeValueForKey:@"visibleCoordinateBounds"]; _mbglMap->cancelTransitions(); + + self.cameraChangeReasonBitmask |= MGLCameraChangeReasonProgrammatic; + _mbglMap->easeTo(cameraOptions, animationOptions); [self didChangeValueForKey:@"visibleCoordinateBounds"]; } @@ -3094,6 +3144,8 @@ public: CGFloat duration = animated ? MGLAnimationDuration : 0; + self.cameraChangeReasonBitmask |= MGLCameraChangeReasonProgrammatic; + if (self.userTrackingMode == MGLUserTrackingModeNone) { _mbglMap->setBearing(direction, @@ -3178,6 +3230,9 @@ public: [self willChangeValueForKey:@"camera"]; _mbglMap->cancelTransitions(); + + self.cameraChangeReasonBitmask |= MGLCameraChangeReasonProgrammatic; + mbgl::CameraOptions cameraOptions = [self cameraOptionsObjectForAnimatingToCamera:camera edgePadding:edgePadding]; _mbglMap->easeTo(cameraOptions, animationOptions); [self didChangeValueForKey:@"camera"]; @@ -3234,6 +3289,9 @@ public: [self willChangeValueForKey:@"camera"]; _mbglMap->cancelTransitions(); + + self.cameraChangeReasonBitmask |= MGLCameraChangeReasonProgrammatic; + mbgl::CameraOptions cameraOptions = [self cameraOptionsObjectForAnimatingToCamera:camera edgePadding:insets]; _mbglMap->flyTo(cameraOptions, animationOptions); [self didChangeValueForKey:@"camera"]; @@ -3394,6 +3452,13 @@ public: return [self metersPerPointAtLatitude:latitude]; } +#pragma mark - Camera Change Reason - + +- (void)resetCameraChangeReason +{ + self.cameraChangeReasonBitmask = MGLCameraChangeReasonNone; +} + #pragma mark - Styling - - (NS_ARRAY_OF(NSURL *) *)bundledStyleURLs @@ -5340,9 +5405,16 @@ public: } } - if ( ! [self isSuppressingChangeDelimiters] && [self.delegate respondsToSelector:@selector(mapView:regionWillChangeAnimated:)]) + if ( ! [self isSuppressingChangeDelimiters] ) { - [self.delegate mapView:self regionWillChangeAnimated:animated]; + if ([self.delegate respondsToSelector:@selector(mapView:regionWillChangeWithReason:animated:)]) + { + [self.delegate mapView:self regionWillChangeWithReason:self.cameraChangeReasonBitmask animated:animated]; + } + else if ([self.delegate respondsToSelector:@selector(mapView:regionWillChangeAnimated:)]) + { + [self.delegate mapView:self regionWillChangeAnimated:animated]; + } } } @@ -5356,8 +5428,12 @@ public: if (!self.scaleBar.hidden) { [(MGLScaleBar *)self.scaleBar setMetersPerPoint:[self metersPerPointAtLatitude:self.centerCoordinate.latitude]]; } - - if ([self.delegate respondsToSelector:@selector(mapViewRegionIsChanging:)]) + + if ([self.delegate respondsToSelector:@selector(mapView:regionIsChangingWithReason:)]) + { + [self.delegate mapView:self regionIsChangingWithReason:self.cameraChangeReasonBitmask]; + } + else if ([self.delegate respondsToSelector:@selector(mapViewRegionIsChanging:)]) { [self.delegate mapViewRegionIsChanging:self]; } @@ -5370,9 +5446,13 @@ public: [self updateCompass]; - if ( ! [self isSuppressingChangeDelimiters] && [self.delegate respondsToSelector:@selector(mapView:regionDidChangeAnimated:)]) + if ( ! [self isSuppressingChangeDelimiters]) { - if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive) + BOOL respondsToSelector = [self.delegate respondsToSelector:@selector(mapView:regionDidChangeAnimated:)]; + BOOL respondsToSelectorWithReason = [self.delegate respondsToSelector:@selector(mapView:regionDidChangeWithReason:animated:)]; + + if ((respondsToSelector || respondsToSelectorWithReason) && + ([UIApplication sharedApplication].applicationState == UIApplicationStateActive)) { _featureAccessibilityElements = nil; _visiblePlaceFeatures = nil; @@ -5384,7 +5464,17 @@ public: UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, nil); } } - [self.delegate mapView:self regionDidChangeAnimated:animated]; + + if (respondsToSelectorWithReason) + { + [self.delegate mapView:self regionDidChangeWithReason:self.cameraChangeReasonBitmask animated:animated]; + } + else if (respondsToSelector) + { + [self.delegate mapView:self regionDidChangeAnimated:animated]; + } + + [self resetCameraChangeReason]; } } |