From b0decd7da97ffc7351cdbb7f750436f3f58958f8 Mon Sep 17 00:00:00 2001 From: Fabian Guerra Date: Tue, 28 Apr 2020 18:44:40 -0500 Subject: [PATCH 1/2] Adds a delegate to notify when a gesture is canceled. --- platform/ios/app/MBXViewController.m | 6 ++++ platform/ios/src/MGLMapView.mm | 30 +++++++++++++++++-- platform/ios/src/MGLMapViewDelegate.h | 16 ++++++++++ .../MGLMapViewDelegateIntegrationTests.swift | 2 ++ 4 files changed, 52 insertions(+), 2 deletions(-) diff --git a/platform/ios/app/MBXViewController.m b/platform/ios/app/MBXViewController.m index af668317c0..b88f8d61b1 100644 --- a/platform/ios/app/MBXViewController.m +++ b/platform/ios/app/MBXViewController.m @@ -2229,6 +2229,12 @@ - (BOOL)mapView:(MGLMapView *)mapView shouldChangeFromCamera:(MGLMapCamera *)old } } +- (void)mapView:(MGLMapView *)mapView didCancelGestureForCamera:(MGLMapCamera *)camera { + MGLMapCamera *toCamera = self.mapView.camera; + toCamera.centerCoordinate = CLLocationCoordinate2DMake(39.748947, -104.995882); + [self.mapView flyToCamera:toCamera withDuration:2.0 completionHandler:nil]; +} + - (void)mapViewRegionIsChanging:(MGLMapView *)mapView { [self updateHUD]; diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index 6b1977d833..26248cd22d 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -1778,6 +1778,10 @@ - (void)handlePanGesture:(UIPanGestureRecognizer *)pan default: self.mbglMap.moveBy({ offset.x, offset.y }, MGLDurationFromTimeInterval(self.decelerationRate)); } + } else { + if ([self.delegate respondsToSelector:@selector(mapView:didCancelGestureForCamera:)]) { + [self.delegate mapView:self didCancelGestureForCamera:toCamera]; + } } } @@ -1869,8 +1873,8 @@ - (void)handlePinchGesture:(UIPinchGestureRecognizer *)pinch // 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 _shouldChangeFromCamera:oldCamera toCamera:toCamera]) + BOOL shouldChange = [self _shouldChangeFromCamera:oldCamera toCamera:toCamera]; + if ( ! shouldChange) { drift = NO; } @@ -1886,6 +1890,9 @@ - (void)handlePinchGesture:(UIPinchGestureRecognizer *)pinch } self.isZooming = NO; + if ( !shouldChange && [self.delegate respondsToSelector:@selector(mapView:didCancelGestureForCamera:)]) { + [self.delegate mapView:self didCancelGestureForCamera:toCamera]; + } [self notifyGestureDidEndWithDrift:drift]; [self unrotateIfNeededForGesture]; } @@ -1999,6 +2006,10 @@ - (void)handleRotateGesture:(UIRotationGestureRecognizer *)rotate { [weakSelf unrotateIfNeededForGesture]; }]; + } else { + if ([self.delegate respondsToSelector:@selector(mapView:didCancelGestureForCamera:)]) { + [self.delegate mapView:self didCancelGestureForCamera:toCamera]; + } } } else @@ -2131,6 +2142,9 @@ - (void)handleDoubleTapGesture:(UITapGestureRecognizer *)doubleTap } else { + if ([self.delegate respondsToSelector:@selector(mapView:didCancelGestureForCamera:)]) { + [self.delegate mapView:self didCancelGestureForCamera:toCamera]; + } [self unrotateIfNeededForGesture]; } } @@ -2169,6 +2183,10 @@ - (void)handleTwoFingerTapGesture:(UITapGestureRecognizer *)twoFingerTap { [weakSelf unrotateIfNeededForGesture]; }]; + } else { + if ([self.delegate respondsToSelector:@selector(mapView:didCancelGestureForCamera:)]) { + [self.delegate mapView:self didCancelGestureForCamera:toCamera]; + } } } @@ -2207,6 +2225,10 @@ - (void)handleQuickZoomGesture:(UILongPressGestureRecognizer *)quickZoom .withZoom(newZoom) .withAnchor(mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y }) .withPadding(MGLEdgeInsetsFromNSEdgeInsets(self.contentInset))); + } else { + if ([self.delegate respondsToSelector:@selector(mapView:didCancelGestureForCamera:)]) { + [self.delegate mapView:self didCancelGestureForCamera:toCamera]; + } } [self cameraIsChanging]; @@ -2275,6 +2297,10 @@ - (void)handleTwoFingerDragGesture:(UIPanGestureRecognizer *)twoFingerDrag .withPitch(pitchNew) .withAnchor(mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y }) .withPadding(MGLEdgeInsetsFromNSEdgeInsets(self.contentInset))); + } else { + if ([self.delegate respondsToSelector:@selector(mapView:didCancelGestureForCamera:)]) { + [self.delegate mapView:self didCancelGestureForCamera:toCamera]; + } } [self cameraIsChanging]; diff --git a/platform/ios/src/MGLMapViewDelegate.h b/platform/ios/src/MGLMapViewDelegate.h index 3ddb7b007f..09fe5921ec 100644 --- a/platform/ios/src/MGLMapViewDelegate.h +++ b/platform/ios/src/MGLMapViewDelegate.h @@ -75,6 +75,22 @@ NS_ASSUME_NONNULL_BEGIN */ - (BOOL)mapView:(MGLMapView *)mapView shouldChangeFromCamera:(MGLMapCamera *)oldCamera toCamera:(MGLMapCamera *)newCamera reason:(MGLCameraChangeReason)reason; +/** +Tells the delegate that the map view canceled a gesture. + +This method is called as soon as `-mapView:shouldChangeFromCamera:toCamera:` +returns `NO`. + +@param mapView The map view that the user is manipulating. +@param camera The camera that triggered a gesture cancellation. + +#### Related examples +See the +Restrict map panning to an area example to learn how to use this method +and `MGLMapCamera` objects to restrict a users ability to pan your map. +*/ +- (void)mapView:(MGLMapView *)mapView didCancelGestureForCamera:(MGLMapCamera *)camera; + /** Tells the delegate that the viewpoint depicted by the map view is about to change. diff --git a/platform/ios/test/MGLMapViewDelegateIntegrationTests.swift b/platform/ios/test/MGLMapViewDelegateIntegrationTests.swift index 172538c65b..5018fbbef7 100644 --- a/platform/ios/test/MGLMapViewDelegateIntegrationTests.swift +++ b/platform/ios/test/MGLMapViewDelegateIntegrationTests.swift @@ -95,6 +95,8 @@ extension MGLMapViewDelegateIntegrationTests: MGLMapViewDelegate { func mapView(_ mapView: MGLMapView, shouldChangeFrom oldCamera: MGLMapCamera, to newCamera: MGLMapCamera, reason: MGLCameraChangeReason) -> Bool { return false } + func mapView(_ mapView: MGLMapView, didCancelGestureFor camera: MGLMapCamera) {} + func mapViewUserLocationAnchorPoint(_ mapView: MGLMapView) -> CGPoint { return CGPoint(x: 100, y: 100) } func mapView(_ mapView: MGLMapView, didFailToLoadImage imageName: String) -> UIImage? { return nil } From 7a247a0f669ade01b34e4e6ef2d2ed5afa1c6ae0 Mon Sep 17 00:00:00 2001 From: Fabian Guerra Date: Wed, 29 Apr 2020 10:00:15 -0500 Subject: [PATCH 2/2] Update changelog --- platform/ios/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md index 553dd9dc96..e0b943bc35 100644 --- a/platform/ios/CHANGELOG.md +++ b/platform/ios/CHANGELOG.md @@ -21,6 +21,7 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT * Fixed an issue where an `MGLMapSnapshotOptions` with an invalid `MGLMapCamera.centerCoordinate`, negative `MGLMapCamera.heading`, negative `MGLMapCamera.pitch`, and negative `MGLMapSnapshotOptions.zoomLevel` resulted in a snapshot centered on Null Island at zoom level 0 even if the style specified a different initial center coordinate or zoom level. ([#280](https://github.com/mapbox/mapbox-gl-native-ios/pull/280)) * Fixed an error that occurred if your implementation of the `-[MGLOfflineStorageDelegate offlineStorage:URLForResourceOfKind:]` method returned a local file URL. ([mapbox/mapbox-gl-native#16428](https://github.com/mapbox/mapbox-gl-native/pull/16428)) * Certain logging statements no longer run on the main thread. ([mapbox/mapbox-gl-native#16325](https://github.com/mapbox/mapbox-gl-native/pull/16325)) +* Added the `-[MGLMapViewDelegate mapView:didCancelGestureForCamera:]` delegate method, which offers an opportunity to take action when the map canceled a gesture. ([#284](https://github.com/mapbox/mapbox-gl-native-ios/pull/284)) ## 5.8.0