Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Commit

Permalink
[ios] Optional positioning and stickiness for callout view
Browse files Browse the repository at this point in the history
  • Loading branch information
frederoni committed Jan 9, 2017
1 parent e162d4f commit c358bc6
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 22 deletions.
7 changes: 7 additions & 0 deletions platform/ios/app/MBXCustomCalloutView.m
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ @implementation MBXCustomCalloutView {
}

@synthesize representedObject = _representedObject;
@synthesize automaticPositioning = _automaticPositioning;
@synthesize staysOpen = _staysOpen;
@synthesize leftAccessoryView = _leftAccessoryView;
@synthesize rightAccessoryView = _rightAccessoryView;
@synthesize delegate = _delegate;
Expand Down Expand Up @@ -66,6 +68,11 @@ - (void)presentCalloutFromRect:(CGRect)rect inView:(UIView *)view constrainedToV
}
}

- (void)setCenter:(CGPoint)center {
center.y = center.y - CGRectGetMidY(self.bounds);
[super setCenter:center];
}

- (void)dismissCalloutAnimated:(BOOL)animated
{
if (self.superview)
Expand Down
34 changes: 28 additions & 6 deletions platform/ios/app/MBXViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ @implementation MBXDroppedPinAnnotation
@end

@interface MBXCustomCalloutAnnotation : MGLPointAnnotation
@property (nonatomic, assign) BOOL automaticPositioning;
@property (nonatomic, assign) BOOL staysOpen;
@end

@implementation MBXCustomCalloutAnnotation
Expand Down Expand Up @@ -699,12 +701,28 @@ - (void)addAnnotationWithCustomCallout
{
[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 w/ auto positioning";
firstAnnotation.automaticPositioning = YES;
firstAnnotation.staysOpen = YES;

MBXCustomCalloutAnnotation *secondAnnotation = [[MBXCustomCalloutAnnotation alloc] init];
secondAnnotation.coordinate = CLLocationCoordinate2DMake(48.8543940, 2.3775439);
secondAnnotation.title = @"Open w/o automatic positioning";
secondAnnotation.automaticPositioning = NO;
secondAnnotation.staysOpen = YES;

MBXCustomCalloutAnnotation *thirdAnnotation = [[MBXCustomCalloutAnnotation alloc] init];
thirdAnnotation.coordinate = CLLocationCoordinate2DMake(48.8553940, 2.3775439);
thirdAnnotation.title = @"Closes";
thirdAnnotation.automaticPositioning = NO;
thirdAnnotation.staysOpen = NO;

NSArray *annotations = @[firstAnnotation, secondAnnotation, thirdAnnotation];
[self.mapView addAnnotations:annotations];

[self.mapView showAnnotations:annotations animated:YES];
}

- (void)styleWaterLayer
Expand Down Expand Up @@ -1582,8 +1600,12 @@ - (void)mapView:(__unused MGLMapView *)mapView didChangeUserTrackingMode:(MGLUse
if ([annotation respondsToSelector:@selector(title)]
&& [annotation isKindOfClass:[MBXCustomCalloutAnnotation class]])
{
MBXCustomCalloutAnnotation *customAnnotation = (MBXCustomCalloutAnnotation *)annotation;

MBXCustomCalloutView *calloutView = [[MBXCustomCalloutView alloc] init];
calloutView.representedObject = annotation;
calloutView.automaticPositioning = customAnnotation.automaticPositioning;
calloutView.staysOpen = customAnnotation.staysOpen;
return calloutView;
}
return nil;
Expand Down
12 changes: 12 additions & 0 deletions platform/ios/src/MGLCalloutView.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,18 @@ NS_ASSUME_NONNULL_BEGIN
*/
@property (nonatomic, weak) id<MGLCalloutViewDelegate> delegate;

/**
A Boolean value indicating whether the callout view should be positioned automatically.
The exact position can be adjusted by overriding -[UIView setCenter:]
*/
@property (nonatomic, assign) BOOL automaticPositioning;

/**
A Boolean value indicating whether the callout view should be dismissed or not
when the map view changes viewport.
*/
@property (nonatomic, assign) BOOL staysOpen;

/**
Presents a callout view by adding it to `view` and pointing at the given rect
of `view`’s bounds. Constrains the callout to the bounds of the given view.
Expand Down
10 changes: 10 additions & 0 deletions platform/ios/src/MGLCompactCalloutView.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@ @implementation MGLCompactCalloutView
}

@synthesize representedObject = _representedObject;
@synthesize automaticPositioning = _automaticPositioning;
@synthesize staysOpen = _staysOpen;

- (instancetype)init {
if (self = [super init]) {
_automaticPositioning = YES;
_staysOpen = YES;
}
return self;
}

+ (instancetype)platformCalloutView
{
Expand Down
41 changes: 25 additions & 16 deletions platform/ios/src/MGLMapView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -4558,21 +4558,30 @@ - (void)notifyMapChange:(mbgl::MapChange)change
|| 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];
BOOL calloutViewStaysOpen = (self.calloutViewForSelectedAnnotation && self.calloutViewForSelectedAnnotation.staysOpen);

if ( ! calloutViewStaysOpen)
{
[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];
}
}
}
}
Expand Down Expand Up @@ -4817,7 +4826,7 @@ - (void)updateCalloutView
UIView <MGLCalloutView> *calloutView = self.calloutViewForSelectedAnnotation;
id <MGLAnnotation> annotation = calloutView.representedObject;

if (calloutView && annotation)
if (calloutView && annotation && calloutView.automaticPositioning)
{
MGLAnnotationTag tag = [self annotationTagForAnnotation:annotation];
MGLAnnotationContext &annotationContext = _annotationContextsByAnnotationTag.at(tag);
Expand Down

0 comments on commit c358bc6

Please sign in to comment.