Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ContentInset for MKMapView

UIScrollView has an excellent contentInset property which tells the view, which portion is visible on the screen. I have an MKMapView which is partially covered by a translucent view. I want the map to be visible under the view. I have to display several annotations on the map, and I want to zoom to them using -setRegion:animated:, but the map view does not respect that it is partially covered, therefore some of my annotations will be covered by the translucent view.

enter image description here

Is there any way to tell the map, to calculate like the scroll view does using contentInset?


UPDATE: This is what I've tried:

- (MKMapRect)mapRectForAnnotations
{
    if (self.trafik) {
        MKMapPoint point = MKMapPointForCoordinate(self.trafik.coordinate);
        MKMapPoint deltaPoint;

        if (self.map.userLocation &&
            self.map.userLocation.coordinate.longitude != 0) {
            MKCoordinateSpan delta = MKCoordinateSpanMake(fabsf(self.trafik.coordinate.latitude-self.map.userLocation.coordinate.latitude),
                                                          fabsf(self.trafik.coordinate.longitude-self.map.userLocation.coordinate.longitude));
            deltaPoint = MKMapPointForCoordinate(CLLocationCoordinate2DMake(delta.latitudeDelta, delta.longitudeDelta));
        } else {
            deltaPoint = MKMapPointForCoordinate(CLLocationCoordinate2DMake(0.01, 0.01));
        }

        return MKMapRectMake(point.x, point.y, deltaPoint.x, deltaPoint.y);
    } else {
        return MKMapRectNull;
    }
}
like image 412
gklka Avatar asked Nov 27 '14 00:11

gklka


2 Answers

Use UIViews's layoutMargins.

E.g. This will force the current user's position pin to move 50pts up.

mapView.layoutMargins = UIEdgeInsets(top: 0.0, left: 0.0, bottom: 100.0, right: 0.0)
like image 129
Jakub Truhlář Avatar answered Oct 19 '22 10:10

Jakub Truhlář


You can do the following but it could mess with other views in your UIViewController that use bottomLayoutGuide. You'll have to test it to find out.

Override bottomLayoutGuide in the UIViewController that has your map as a subview and return a MyLayoutGuide object that looks like:

@interface MyLayoutGuide : NSObject <UILayoutSupport>
@property (nonatomic) CGFloat length;
-(id)initWithLength:(CGFloat)length;
@end

@implementation MyLayoutGuide
@synthesize length = _length;
@synthesize topAnchor = _topAnchor;
@synthesize bottomAnchor = _bottomAnchor;
@synthesize heightAnchor = _heightAnchor;

- (id)initWithLength:(CGFloat)length
{
    if (self = [super init]) {
        _length = length;
    }
    return self;
}

@end

bottomLayoutGuide that insets the MKMapView by 50 points:

- (id)bottomLayoutGuide
{
    CGFloat bottomLayoutGuideLength = 50.f;

    return [[MyLayoutGuide alloc] initWithLength:bottomLayoutGuideLength];
}

You can force this "inset" to be calculated again by calling setNeedsLayout on your MKMapView in the event that your time table on the bottom changes size. We've created a helper in our MKMapView subclass that can be called from the parent UIViewController:

- (void)updateBottomLayoutGuides
{
    // this method ends up calling -(id)bottomLayoutGuide on its UIViewController
    // and thus updating where the Legal link on the map should be.
    [self.mapView setNeedsLayout];
}

Answer adapted from this answer.

like image 32
Matt Robinson Avatar answered Oct 19 '22 10:10

Matt Robinson