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

Reposition map to fit callouts #2412

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 8 additions & 0 deletions include/mbgl/ios/MGLMapView.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@ IB_DESIGNABLE
* @return An initialized map view. */
- (instancetype)initWithFrame:(CGRect)frame styleURL:(nullable NSURL *)styleURL;

/** Edge insets for positioning callouts.
*
* If your `MGLMapView` is obstructed by transparent navbars or toolbars you may want to set the top and bottom insets to the
* top and bottom layout guides from your view controller.
*
* The default value of this property is `UIEdgeInsetsZero`. */
@property(nonatomic) UIEdgeInsets calloutInsets;

#pragma mark - Accessing Map Properties

/** @name Accessing Map Properties */
Expand Down
30 changes: 28 additions & 2 deletions platform/ios/MGLMapView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ @interface MGLMapView () <UIGestureRecognizerDelegate,
@property (nonatomic) CGFloat quickZoomStart;
@property (nonatomic, getter=isDormant) BOOL dormant;
@property (nonatomic, readonly, getter=isRotationAllowed) BOOL rotationAllowed;
@property (nonatomic, strong) SMCalloutView *repositioningCalloutView;

@end

Expand Down Expand Up @@ -268,6 +269,8 @@ - (void)commonInit

_annotationImages = [NSMutableDictionary dictionary];

_calloutInsets = UIEdgeInsetsZero;

// setup logo bug
//
UIImage *logo = [[MGLMapView resourceImageNamed:@"mapbox.png"] imageWithAlignmentRectInsets:UIEdgeInsetsMake(1.5, 4, 3.5, 2)];
Expand Down Expand Up @@ -1976,6 +1979,11 @@ CLLocationCoordinate2D MGLLocationCoordinate2DFromLatLng(mbgl::LatLng latLng)
return bounds;
}

- (CGRect)viewportRectWithInsets:(UIEdgeInsets)insets
{
return CGRectMake(insets.left, insets.top, self.bounds.size.width - (insets.left + insets.right), self.bounds.size.height - (insets.top + insets.bottom));
}

#pragma mark - Styling -

- (NS_ARRAY_OF(NSURL *) *)bundledStyleURLs
Expand Down Expand Up @@ -2431,10 +2439,14 @@ - (void)selectAnnotation:(id <MGLAnnotation>)annotation animated:(BOOL)animated
// set annotation delegate to handle taps on the callout view
self.selectedAnnotationCalloutView.delegate = self;

// create constraining view based on user insets
CGRect viewportRect = [self viewportRectWithInsets:self.calloutInsets];
UIView *constrainingView = [UIView.alloc initWithFrame:viewportRect];

// present popup
[self.selectedAnnotationCalloutView presentCalloutFromRect:calloutBounds
inView:self.glView
constrainedToView:self.glView
constrainedToView:constrainingView
animated:animated];
}

Expand All @@ -2445,6 +2457,16 @@ - (void)selectAnnotation:(id <MGLAnnotation>)annotation animated:(BOOL)animated
}
}

- (NSTimeInterval)calloutView:(SMCalloutView *)calloutView delayForRepositionWithSize:(CGSize)offset
{
self.repositioningCalloutView = calloutView;

_mbglMap->moveBy(offset.width, offset.height, secondsAsDuration(MGLAnimationDuration));
calloutView.frame = CGRectOffset(calloutView.frame, offset.width, offset.height);

return MGLAnimationDuration;
}

- (SMCalloutView *)calloutViewForAnnotation:(id <MGLAnnotation>)annotation
{
SMCalloutView *calloutView = [SMCalloutView platformCalloutView];
Expand Down Expand Up @@ -2899,7 +2921,11 @@ - (void)notifyMapChange:(mbgl::MapChange)change
case mbgl::MapChangeRegionWillChange:
case mbgl::MapChangeRegionWillChangeAnimated:
{
[self deselectAnnotation:self.selectedAnnotation animated:NO];
// Don't deselect the annotation if we are repositioning to fit a callout view.
if (!self.repositioningCalloutView) {
[self deselectAnnotation:self.selectedAnnotation animated:NO];
}
self.repositioningCalloutView = nil;

if ( ! [self isSuppressingChangeDelimiters] && [self.delegate respondsToSelector:@selector(mapView:regionWillChangeAnimated:)])
{
Expand Down