summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFredrik Karlsson <bjorn.fredrik.karlsson@gmail.com>2017-01-09 17:24:07 +0100
committerMinh Nguyễn <mxn@1ec5.org>2017-01-11 15:48:08 -0800
commitf1fc9bdfeb9ba107d27242ee4618228c204e98a3 (patch)
treeb19ffb83b632cdb4d1b2539be8045c8b370d0293
parent57644b2804a3d27ff19a58e0f3015d83264833ab (diff)
downloadqtlocation-mapboxgl-f1fc9bdfeb9ba107d27242ee4618228c204e98a3.tar.gz
[ios] Optional positioning and stickiness for callout view
-rw-r--r--platform/ios/app/MBXCustomCalloutView.h4
-rw-r--r--platform/ios/app/MBXCustomCalloutView.m7
-rw-r--r--platform/ios/app/MBXViewController.m33
-rw-r--r--platform/ios/src/MGLCalloutView.h18
-rw-r--r--platform/ios/src/MGLCompactCalloutView.m8
-rw-r--r--platform/ios/src/MGLMapView.mm50
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);