From 68a9e2ea926db80010ade77cda77ced53d412b28 Mon Sep 17 00:00:00 2001 From: Jason Wray Date: Fri, 5 Jan 2018 04:06:44 -0500 Subject: [PATCH] [ios] Provide haptic feedback when user rotates to due north --- platform/ios/CHANGELOG.md | 1 + platform/ios/src/MGLMapView.h | 13 +++++++++++++ platform/ios/src/MGLMapView.mm | 21 +++++++++++++++++++++ 3 files changed, 35 insertions(+) diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md index 9eb522f2b..b0f3e741e 100644 --- a/platform/ios/CHANGELOG.md +++ b/platform/ios/CHANGELOG.md @@ -48,6 +48,7 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT * Labels are now transliterated from more languages when VoiceOver is enabled. ([#10881](https://github.com/mapbox/mapbox-gl-native/pull/10881)) * Long-pressing the attribution button causes the SDK’s version number to be displayed in the action sheet that appears. ([#10650](https://github.com/mapbox/mapbox-gl-native/pull/10650)) * Reduced offline download size for styles with symbol layers that render only icons, and no text. ([#11055](https://github.com/mapbox/mapbox-gl-native/pull/11055)) +* Added haptic feedback that occurs when the user rotates the map to due north, configurable via `MGLMapView.hapticFeedbackEnabled`. ([#10847](https://github.com/mapbox/mapbox-gl-native/pull/10847)) ## 3.7.5 - February 16, 2018 diff --git a/platform/ios/src/MGLMapView.h b/platform/ios/src/MGLMapView.h index 9c18965b0..44130f3c6 100644 --- a/platform/ios/src/MGLMapView.h +++ b/platform/ios/src/MGLMapView.h @@ -483,6 +483,19 @@ MGL_EXPORT IB_DESIGNABLE */ @property(nonatomic, getter=isPitchEnabled) BOOL pitchEnabled; +/** + A Boolean value that determines whether the user will receive haptic feedback + for certain interactions with the map. + + When this property is set to `YES`, the default, a `UIImpactFeedbackStyleLight` + haptic feedback event be played when the user rotates the map to due north + (0°). + + This feature requires a device that supports haptic feedback, running iOS 10 or + newer. + */ +@property(nonatomic, getter=isHapticFeedbackEnabled) BOOL hapticFeedbackEnabled; + /** A floating-point value that determines the rate of deceleration after the user lifts their finger. diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index 1cb477955..bb8948150 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -228,6 +228,7 @@ public: @property (nonatomic) CGFloat quickZoomStart; @property (nonatomic, getter=isDormant) BOOL dormant; @property (nonatomic, readonly, getter=isRotationAllowed) BOOL rotationAllowed; +@property (nonatomic) BOOL shouldTriggerHapticFeedbackForCompass; @property (nonatomic) MGLMapViewProxyAccessibilityElement *mapViewProxyAccessibilityElement; @property (nonatomic) MGLAnnotationContainerView *annotationContainerView; @property (nonatomic) MGLUserLocation *userLocation; @@ -525,6 +526,8 @@ public: [_twoFingerTap requireGestureRecognizerToFail:_twoFingerDrag]; [self addGestureRecognizer:_twoFingerTap]; + _hapticFeedbackEnabled = YES; + _decelerationRate = MGLMapViewDecelerationRateNormal; _quickZoom = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleQuickZoomGesture:)]; @@ -1513,6 +1516,8 @@ public: self.userTrackingMode = MGLUserTrackingModeFollow; } + self.shouldTriggerHapticFeedbackForCompass = NO; + [self notifyGestureDidBegin]; } else if (rotate.state == UIGestureRecognizerStateChanged) @@ -1535,6 +1540,22 @@ public: } [self cameraIsChanging]; + + // Trigger a light haptic feedback event when the user rotates to due north. + if (@available(iOS 10.0, *)) + { + if (self.isHapticFeedbackEnabled && fabs(newDegrees) <= 1 && self.shouldTriggerHapticFeedbackForCompass) + { + UIImpactFeedbackGenerator *hapticFeedback = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleLight]; + [hapticFeedback impactOccurred]; + + self.shouldTriggerHapticFeedbackForCompass = NO; + } + else if (fabs(newDegrees) > 1) + { + self.shouldTriggerHapticFeedbackForCompass = YES; + } + } } else if (rotate.state == UIGestureRecognizerStateEnded || rotate.state == UIGestureRecognizerStateCancelled) {