Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting a MapView's center coordinate does not take into account full size of MapView (off-screen portion)

The Problem

I have a view that includes a full-screen MKMapView. The bottom half of the MapView is covered with a TableView that has translucent cells so that the map shows through.

User location annotation blocked by TableView

When I center on an annotation coordinate, the current location for example, the annotation view is blocked by the TableView.

- (void)centerOnCurrentLocation
{
    MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(self.locationManager.location.coordinate, 50000, 50000);
    [self.mapView setRegion:[self.mapView regionThatFits:region] animated:YES];
}

Attempted Solution

I first tried to programmatically shift the map to offset the center, shifting the annotation up. This approach works if I turn off animation, though it's not a simple solution. Nor do I want to turn off animation.

Instead I thought that if I extend the MapView off the top of the screen by the same height as the TableView the center of the MapView would be exactly where I want it. It doesn't work! When I set the center coordinate on the larger MapView the annotation still appears in the center of the screen, not in the center of the larger MapView. It seems like MKMapView is using the view's visible region when calculating its center.

Enlarged MapView

This is what I would expect to see when I center on current location using the enlarged MapView.

This is what I want to see when I center on current location.

If only MKMapView had a centerOffset property that allowed you to shift the center by some CGPoint.

Does anybody have a simple, elegant solution to offset a MapView's center?

like image 479
Michael B. Avatar asked Jan 31 '26 09:01

Michael B.


1 Answers

Just to clarify on my comment, you can use setVisibleMapRect: edgePadding: to create the offset you want. You will need to put it in the mapView delegate method regionDidChangeAnimated: this will fire anytime the region changes on your map so you need to wrap your code with a flag to know when to apply the offset or it can be applied multiple times. Here is what you need to do:

- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated{

    if (!self.mapInsetsSet) {
        self.mapInsetsSet=TRUE;
        [self.myMapView setVisibleMapRect:self.myMapView.visibleMapRect edgePadding:UIEdgeInsetsMake(10, 0, 0, 0) animated:YES];
    }

}

In the above code, mapInsetsSet is just a bool that you can set elsewhere to control when to apply the offset. Also, you will need to adjust the UIEdgeInsetsMake to the desired offset.

like image 172
rmp Avatar answered Feb 02 '26 01:02

rmp



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!