diff options
author | Fredrik Karlsson <bjorn.fredrik.karlsson@gmail.com> | 2017-01-09 17:24:07 +0100 |
---|---|---|
committer | Minh Nguyễn <mxn@1ec5.org> | 2017-01-11 15:48:08 -0800 |
commit | f1fc9bdfeb9ba107d27242ee4618228c204e98a3 (patch) | |
tree | b19ffb83b632cdb4d1b2539be8045c8b370d0293 | |
parent | 57644b2804a3d27ff19a58e0f3015d83264833ab (diff) | |
download | qtlocation-mapboxgl-f1fc9bdfeb9ba107d27242ee4618228c204e98a3.tar.gz |
[ios] Optional positioning and stickiness for callout view
-rw-r--r-- | platform/ios/app/MBXCustomCalloutView.h | 4 | ||||
-rw-r--r-- | platform/ios/app/MBXCustomCalloutView.m | 7 | ||||
-rw-r--r-- | platform/ios/app/MBXViewController.m | 33 | ||||
-rw-r--r-- | platform/ios/src/MGLCalloutView.h | 18 | ||||
-rw-r--r-- | platform/ios/src/MGLCompactCalloutView.m | 8 | ||||
-rw-r--r-- | platform/ios/src/MGLMapView.mm | 50 |
6 files changed, 98 insertions, 22 deletions
diff --git a/platform/ios/app/MBXCustomCalloutView.h b/platform/ios/app/MBXCustomCalloutView.h index a61619b79f..961f2d7f6a 100644 --- a/platform/ios/app/MBXCustomCalloutView.h +++ b/platform/ios/app/MBXCustomCalloutView.h @@ -7,4 +7,8 @@ * callout title for demonstration purpose. */ @interface MBXCustomCalloutView : UIView <MGLCalloutView> + +@property (nonatomic, assign, getter=isAnchoredToAnnotation) BOOL anchoredToAnnotation; +@property (nonatomic, assign) BOOL dismissesAutomatically; + @end diff --git a/platform/ios/app/MBXCustomCalloutView.m b/platform/ios/app/MBXCustomCalloutView.m index 9edc00f6e9..e46b727d84 100644 --- a/platform/ios/app/MBXCustomCalloutView.m +++ b/platform/ios/app/MBXCustomCalloutView.m @@ -17,6 +17,8 @@ static CGFloat const tipWidth = 10.0; } @synthesize representedObject = _representedObject; +@synthesize anchoredToAnnotation = _anchoredToAnnotation; +@synthesize dismissesAutomatically = _dismissesAutomatically; @synthesize leftAccessoryView = _leftAccessoryView; @synthesize rightAccessoryView = _rightAccessoryView; @synthesize delegate = _delegate; @@ -66,6 +68,11 @@ static CGFloat const tipWidth = 10.0; } } +- (void)setCenter:(CGPoint)center { + center.y = center.y - CGRectGetMidY(self.bounds); + [super setCenter:center]; +} + - (void)dismissCalloutAnimated:(BOOL)animated { if (self.superview) diff --git a/platform/ios/app/MBXViewController.m b/platform/ios/app/MBXViewController.m index 496c30efc9..13401997a0 100644 --- a/platform/ios/app/MBXViewController.m +++ b/platform/ios/app/MBXViewController.m @@ -89,6 +89,8 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) { @end @interface MBXCustomCalloutAnnotation : MGLPointAnnotation +@property (nonatomic, assign) BOOL anchoredToAnnotation; +@property (nonatomic, assign) BOOL dismissesAutomatically; @end @implementation MBXCustomCalloutAnnotation @@ -699,12 +701,28 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) { { [self.mapView removeAnnotations:self.mapView.annotations]; - MBXCustomCalloutAnnotation *annotation = [[MBXCustomCalloutAnnotation alloc] init]; - annotation.coordinate = CLLocationCoordinate2DMake(48.8533940, 2.3775439); - annotation.title = @"Custom Callout"; - - [self.mapView addAnnotation:annotation]; - [self.mapView showAnnotations:@[annotation] animated:YES]; + MBXCustomCalloutAnnotation *firstAnnotation = [[MBXCustomCalloutAnnotation alloc] init]; + firstAnnotation.coordinate = CLLocationCoordinate2DMake(48.8533940, 2.3775439); + firstAnnotation.title = @"Open anchored to annotation"; + firstAnnotation.anchoredToAnnotation = YES; + firstAnnotation.dismissesAutomatically = NO; + + MBXCustomCalloutAnnotation *secondAnnotation = [[MBXCustomCalloutAnnotation alloc] init]; + secondAnnotation.coordinate = CLLocationCoordinate2DMake(48.8543940, 2.3775439); + secondAnnotation.title = @"Open not anchored to annotation"; + secondAnnotation.anchoredToAnnotation = NO; + secondAnnotation.dismissesAutomatically = NO; + + MBXCustomCalloutAnnotation *thirdAnnotation = [[MBXCustomCalloutAnnotation alloc] init]; + thirdAnnotation.coordinate = CLLocationCoordinate2DMake(48.8553940, 2.3775439); + thirdAnnotation.title = @"Dismisses automatically"; + thirdAnnotation.anchoredToAnnotation = YES; + thirdAnnotation.dismissesAutomatically = YES; + + NSArray *annotations = @[firstAnnotation, secondAnnotation, thirdAnnotation]; + [self.mapView addAnnotations:annotations]; + + [self.mapView showAnnotations:annotations animated:YES]; } - (void)styleWaterLayer @@ -1582,8 +1600,11 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) { if ([annotation respondsToSelector:@selector(title)] && [annotation isKindOfClass:[MBXCustomCalloutAnnotation class]]) { + MBXCustomCalloutAnnotation *customAnnotation = (MBXCustomCalloutAnnotation *)annotation; MBXCustomCalloutView *calloutView = [[MBXCustomCalloutView alloc] init]; calloutView.representedObject = annotation; + calloutView.anchoredToAnnotation = customAnnotation.anchoredToAnnotation; + calloutView.dismissesAutomatically = customAnnotation.dismissesAutomatically; return calloutView; } return nil; diff --git a/platform/ios/src/MGLCalloutView.h b/platform/ios/src/MGLCalloutView.h index 6918aad614..4dc9a25be4 100644 --- a/platform/ios/src/MGLCalloutView.h +++ b/platform/ios/src/MGLCalloutView.h @@ -46,6 +46,24 @@ NS_ASSUME_NONNULL_BEGIN */ - (void)dismissCalloutAnimated:(BOOL)animated; +@optional + +/** + A Boolean value indicating whether the callout view should be anchored to + the corresponding annotation. You can adjust the callout view’s precise location by + overriding -[UIView setCenter:]. The callout view will not be anchored to the + annotation if this optional property is unimplemented. + */ +@property (nonatomic, readonly, assign, getter=isAnchoredToAnnotation) BOOL anchoredToAnnotation; + +/** + A Boolean value indicating whether the callout view should be dismissed automatically + when the map view’s viewport changes. Note that a single tap on the map view + still dismisses the callout view regardless of the value of this property. + The callout view will be dismissed if this optional property is unimplemented. + */ +@property (nonatomic, readonly, assign) BOOL dismissesAutomatically; + @end /** diff --git a/platform/ios/src/MGLCompactCalloutView.m b/platform/ios/src/MGLCompactCalloutView.m index 49812c51a4..3d2118ca38 100644 --- a/platform/ios/src/MGLCompactCalloutView.m +++ b/platform/ios/src/MGLCompactCalloutView.m @@ -14,6 +14,14 @@ return [[self alloc] init]; } +- (BOOL)isAnchoredToAnnotation { + return YES; +} + +- (BOOL)dismissesAutomatically { + return NO; +} + - (void)setRepresentedObject:(id <MGLAnnotation>)representedObject { _representedObject = representedObject; diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index f8ca673093..c85746d1b5 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -4561,21 +4561,34 @@ public: || self.userTrackingMode == MGLUserTrackingModeNone || self.userTrackingState != MGLUserTrackingStateChanged) { - // Deselect annotation if it lies outside the viewport - if (self.selectedAnnotation) { - MGLAnnotationTag tag = [self annotationTagForAnnotation:self.selectedAnnotation]; - MGLAnnotationContext &annotationContext = _annotationContextsByAnnotationTag.at(tag); - MGLAnnotationView *annotationView = annotationContext.annotationView; - - CGRect rect = [self positioningRectForCalloutForAnnotationWithTag:tag]; - - if (annotationView) - { - rect = annotationView.frame; - } - - if ( ! CGRectIntersectsRect(rect, self.frame)) { - [self deselectAnnotation:self.selectedAnnotation animated:NO]; + UIView<MGLCalloutView> *calloutView = self.calloutViewForSelectedAnnotation; + BOOL dismissesAutomatically = (calloutView + && [calloutView respondsToSelector:@selector(dismissesAutomatically)] + && calloutView.dismissesAutomatically); + // dismissesAutomatically is an optional property and we want to dismiss + // the callout view if it's unimplemented. + if (dismissesAutomatically || ![calloutView respondsToSelector:@selector(dismissesAutomatically)]) + { + [self deselectAnnotation:self.selectedAnnotation animated:NO]; + } + else + { + // Deselect annotation if it lies outside the viewport + if (self.selectedAnnotation) { + MGLAnnotationTag tag = [self annotationTagForAnnotation:self.selectedAnnotation]; + MGLAnnotationContext &annotationContext = _annotationContextsByAnnotationTag.at(tag); + MGLAnnotationView *annotationView = annotationContext.annotationView; + + CGRect rect = [self positioningRectForCalloutForAnnotationWithTag:tag]; + + if (annotationView) + { + rect = annotationView.frame; + } + + if ( ! CGRectIntersectsRect(rect, self.frame)) { + [self deselectAnnotation:self.selectedAnnotation animated:NO]; + } } } } @@ -4816,7 +4829,12 @@ public: UIView <MGLCalloutView> *calloutView = self.calloutViewForSelectedAnnotation; id <MGLAnnotation> annotation = calloutView.representedObject; - if (calloutView && annotation) + BOOL isAnchoredToAnnotation = (calloutView + && annotation + && [calloutView respondsToSelector:@selector(isAnchoredToAnnotation)] + && calloutView.isAnchoredToAnnotation); + + if (isAnchoredToAnnotation) { MGLAnnotationTag tag = [self annotationTagForAnnotation:annotation]; MGLAnnotationContext &annotationContext = _annotationContextsByAnnotationTag.at(tag); |