ContentInset for MKMapView
Asked Answered
S

2

12

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;
    }
}
Stanislaus answered 27/11, 2014 at 0:28 Comment(2)
Yes, the setVisibleMapRect:edgePadding:animated: method should help you. Calculate the MKMapRect that fits the annotations then add edge padding as needed. See https://mcmap.net/q/127209/-zooming-mkmapview-to-fit-annotation-pins for an example of how to calculate the MKMapRect.Dissatisfactory
I've updated my question to include my attempt to calculate this MKMapRect, but it hast to be wrong somewhere, because I always get a full world map. :(Stanislaus
A
3

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.

Albion answered 27/7, 2016 at 23:28 Comment(0)
E
12

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)
Elephant answered 14/10, 2018 at 9:15 Comment(0)
A
3

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.

Albion answered 27/7, 2016 at 23:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.