[ios] Optional positioning and stickiness for callout view

This commit is contained in:
Fredrik Karlsson
2017-01-09 17:24:07 +01:00
committed by Minh Nguyễn
parent 57644b2804
commit f1fc9bdfeb
6 changed files with 97 additions and 21 deletions

View File

@@ -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

View File

@@ -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)

View File

@@ -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";
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;
[self.mapView addAnnotation:annotation];
[self.mapView showAnnotations:@[annotation] animated:YES];
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;

View File

@@ -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
/**

View File

@@ -14,6 +14,14 @@
return [[self alloc] init];
}
- (BOOL)isAnchoredToAnnotation {
return YES;
}
- (BOOL)dismissesAutomatically {
return NO;
}
- (void)setRepresentedObject:(id <MGLAnnotation>)representedObject
{
_representedObject = representedObject;

View File

@@ -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);