diff options
author | Julian Rex <julian.rex@mapbox.com> | 2018-09-25 21:58:59 -0400 |
---|---|---|
committer | Julian Rex <julian.rex@mapbox.com> | 2018-10-06 00:58:40 -0400 |
commit | 5bfe397a176cd72e80296b3bc24b5af654b8e987 (patch) | |
tree | 5f4a634f7ecfa6778c058f8843f977e8aa83bb48 | |
parent | 91ea258dde2a715170da2850e327507b77eff6c6 (diff) | |
download | qtlocation-mapboxgl-5bfe397a176cd72e80296b3bc24b5af654b8e987.tar.gz |
Added WIP delegate methods to handle annotations' selection animations and behaviour
-rw-r--r-- | platform/ios/src/MGLMapView.h | 12 | ||||
-rw-r--r-- | platform/ios/src/MGLMapView.mm | 63 | ||||
-rw-r--r-- | platform/ios/src/MGLMapViewDelegate.h | 29 |
3 files changed, 79 insertions, 25 deletions
diff --git a/platform/ios/src/MGLMapView.h b/platform/ios/src/MGLMapView.h index 5312804cd2..8fdd346379 100644 --- a/platform/ios/src/MGLMapView.h +++ b/platform/ios/src/MGLMapView.h @@ -1318,6 +1318,10 @@ MGL_EXPORT IB_DESIGNABLE @property (nonatomic, copy) NSArray<id <MGLAnnotation>> *selectedAnnotations; /** + TODO: update documentation + TODO: consider deprecation, and replacing with a `selectAnnotation:` that uses the proposed delegate + methods. + Selects an annotation and displays its callout view. The `animated` parameter determines whether the map is panned to bring the @@ -1325,14 +1329,18 @@ MGL_EXPORT IB_DESIGNABLE | `animated` parameter | Effect | |------------------|--------| - | `NO` | The annotation is selected, and the callout is presented. However the map is not panned to bring the annotation or callout onscreen. The presentation of the callout is animated. | + | `NO` | The annotation is selected, and the callout is presented. However the map is not panned to bring the annotation or callout onscreen. | `YES` | The annotation is selected, and the callout is presented. If the annotation is offscreen *and* is of type `MGLPointAnnotation`, the map is panned so that the annotation and its callout are brought just onscreen. The annotation is *not* centered within the viewport. | @param annotation The annotation object to select. - @param animated If `YES`, the annotation and callout view are animated on-screen. + @param animated If `YES`, the annotation and callout view are moved on-screen. @note In versions prior to `4.0.0` selecting an offscreen annotation did not change the camera. + + @note The `animated` parameter can be considered the same as the value returned from + `-[MGLMapViewDelgate mapView:shouldMoveOnscreenWhenSelectingAnnotation:]`. + See also `-[MGLMapViewDelegate mapView:shouldAnimateAnnotationSelection:` for animation control */ - (void)selectAnnotation:(id <MGLAnnotation>)annotation animated:(BOOL)animated; diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index e9fd568a04..b68b0f4352 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -1712,7 +1712,14 @@ public: { CGPoint calloutPoint = [singleTap locationInView:self]; CGRect positionRect = [self positioningRectForAnnotation:annotation defaultCalloutPoint:calloutPoint]; - [self selectAnnotation:annotation moveOnscreen:YES animateSelection:YES calloutPositioningRect:positionRect]; + + BOOL moveOnscreen = YES; + + if ([self.delegate respondsToSelector:@selector(mapView:shouldMoveOnscreenWhenSelectingAnnotation:)]) { + moveOnscreen = [self.delegate mapView:self shouldMoveOnscreenWhenSelectingAnnotation:annotation]; + } + + [self selectAnnotation:annotation moveOnscreen:moveOnscreen calloutPositioningRect:positionRect]; } else if (self.selectedAnnotation) { @@ -4370,10 +4377,11 @@ public: - (void)selectAnnotation:(id <MGLAnnotation>)annotation animated:(BOOL)animated { CGRect positioningRect = [self positioningRectForAnnotation:annotation defaultCalloutPoint:CGPointZero]; - [self selectAnnotation:annotation moveOnscreen:animated animateSelection:YES calloutPositioningRect:positioningRect]; + + [self selectAnnotation:annotation moveOnscreen:animated calloutPositioningRect:positioningRect]; } -- (void)selectAnnotation:(id <MGLAnnotation>)annotation moveOnscreen:(BOOL)moveOnscreen animateSelection:(BOOL)animateSelection calloutPositioningRect:(CGRect)calloutPositioningRect +- (void)selectAnnotation:(id <MGLAnnotation>)annotation moveOnscreen:(BOOL)moveOnscreen calloutPositioningRect:(CGRect)calloutPositioningRect { if ( ! annotation) return; @@ -4381,6 +4389,12 @@ public: [self deselectAnnotation:self.selectedAnnotation animated:NO]; + BOOL animateSelection = YES; + + if ([self.delegate respondsToSelector:@selector(mapView:shouldAnimateAnnotationSelection:)]) { + animateSelection = [self.delegate mapView:self shouldAnimateAnnotationSelection:annotation]; + } + // Add the annotation to the map if it hasn’t been added yet. MGLAnnotationTag annotationTag = [self annotationTagForAnnotation:annotation]; if (annotationTag == MGLAnnotationTagNotFound && annotation != self.userLocation) @@ -4407,11 +4421,6 @@ public: self.selectedAnnotation = annotation; - // Determine if we're allowed to move this offscreen annotation on screen, even though we've asked it to - if (moveOnscreen) { - moveOnscreen = [self isBringingAnnotationOnscreenSupportedForAnnotation:annotation animated:animateSelection]; - } - // If we have an invalid positioning rect, we need to provide a suitable default. // This (currently) happens if you select an annotation that has NOT yet been // added. See https://github.com/mapbox/mapbox-gl-native/issues/11476 @@ -4504,29 +4513,37 @@ public: moveOnscreen = NO; // Need to consider the content insets. - CGRect bounds = UIEdgeInsetsInsetRect(self.bounds, self.contentInset); + CGRect bounds = constrainedRect; // Any one of these cases should trigger a move onscreen - if (CGRectGetMinX(calloutPositioningRect) < CGRectGetMinX(bounds)) - { - constrainedRect.origin.x = expandedPositioningRect.origin.x; + CGFloat minX = CGRectGetMinX(expandedPositioningRect); + + if (minX < CGRectGetMinX(bounds)) { + constrainedRect.origin.x = minX; moveOnscreen = YES; } - else if (CGRectGetMaxX(calloutPositioningRect) > CGRectGetMaxX(bounds)) - { - constrainedRect.origin.x = CGRectGetMaxX(expandedPositioningRect) - constrainedRect.size.width; - moveOnscreen = YES; + else { + CGFloat maxX = CGRectGetMaxX(expandedPositioningRect); + + if (maxX > CGRectGetMaxX(bounds)) { + constrainedRect.origin.x = maxX - CGRectGetWidth(constrainedRect); + moveOnscreen = YES; + } } - if (CGRectGetMinY(calloutPositioningRect) < CGRectGetMinY(bounds)) - { - constrainedRect.origin.y = expandedPositioningRect.origin.y; + CGFloat minY = CGRectGetMinY(expandedPositioningRect); + + if (minY < CGRectGetMinY(bounds)) { + constrainedRect.origin.y = minY; moveOnscreen = YES; } - else if (CGRectGetMaxY(calloutPositioningRect) > CGRectGetMaxY(bounds)) - { - constrainedRect.origin.y = CGRectGetMaxY(expandedPositioningRect) - constrainedRect.size.height; - moveOnscreen = YES; + else { + CGFloat maxY = CGRectGetMaxY(expandedPositioningRect); + + if (maxY > CGRectGetMaxY(bounds)) { + constrainedRect.origin.y = maxY - CGRectGetHeight(constrainedRect); + moveOnscreen = YES; + } } } diff --git a/platform/ios/src/MGLMapViewDelegate.h b/platform/ios/src/MGLMapViewDelegate.h index 77dd2e4ef4..596124ff93 100644 --- a/platform/ios/src/MGLMapViewDelegate.h +++ b/platform/ios/src/MGLMapViewDelegate.h @@ -459,6 +459,35 @@ NS_ASSUME_NONNULL_BEGIN */ - (BOOL)mapView:(MGLMapView *)mapView shapeAnnotationIsEnabled:(MGLShape *)annotation; + +/** + TODO: document + Returns a Boolean value indicating whether the annotation should be moved on-screen. + + If the delegate does not implement this method, the default is `YES`. + + This method is useful in cases where the selection is not programmatic (e.g. user taps an annotation) + The value returned from this method can be considered the same as the `animated` parameter passed to + `-selectAnnotation:animated:` + */ +- (BOOL)mapView:(MGLMapView *)mapView shouldMoveOnscreenWhenSelectingAnnotation:(id <MGLAnnotation>)annotation; + + +/** + TODO: document + Returns a Boolean value indicating whether the annotation's visual changes should be animated. + Specifically this controls: + - The annotation's selection change + - The presentation of the annotation's callout (if applicable) + - When moving an off-screen annotation, whether that movement is animated. + + If the delegate does not implement this method, the default is `YES`. + + The value returned from this method is NOT the same as the `animated` parameter passed to + `-selectAnnotation:animated:` + */ +- (BOOL)mapView:(MGLMapView *)mapView shouldAnimateAnnotationSelection:(id <MGLAnnotation>)annotation; + /** Tells the delegate that one of its annotations was selected. |