I have the following problem:
I have a "drawn map" (image) which I add to the MapView as an Overlay. No Problem with that.. but I need to limit the MapView to the region of the Overlay, so a user isn't able to scroll/zoom outside of this region.. but it should be possible to scroll/zoom inside the "bounds" of the overlay - means I cannot just disable zoom/scrolling for the MapView.
Are there any ideas/solution on this topic? The reason for using the MapView/-Kit is that I need to add various POIs to the custom map. This may become more complex when just using an ImageView+ScrollView for presenting the custom map.
I've researched alot on this topic, but I didn't found a nice solution.
Any help is appreciated!
Best Regards, Christian
Edit: This is our solution: You supply a topleft and a bottomright coordinate to limit the map. The (minimum) zoomlevel is also limited. I've deactivated decelerating and you are able to bounce a bit out of the map (for better performance/ux). I added a ~1km grey border to the overlay so the user isnÄt able to see the orignal worldmap of google.
LimitedMapView.h:
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
@interface LimitedMapView : MKMapView <UIScrollViewDelegate>{
}
@property (nonatomic, assign) CLLocationCoordinate2D topLeftCoordinate;
@property (nonatomic, assign) CLLocationCoordinate2D bottomRightCoordinate;
@end
LimitedMapView.m:
#import "LimitedMapView.h"
@implementation LimitedMapView
@synthesize topLeftCoordinate, bottomRightCoordinate;
- (void)scrollViewDidZoom:(UIScrollView *)scrollView{
if([super respondsToSelector:@selector(scrollViewDidZoom:)]) [super scrollViewDidZoom:scrollView];
if ([self region].span.latitudeDelta > 0.002401f || [self region].span.longitudeDelta > 0.003433f) {
CLLocationCoordinate2D center = self.centerCoordinate;
MKCoordinateSpan span = MKCoordinateSpanMake(0.002401f, 0.003433f);
self.region = MKCoordinateRegionMake(center, span);
}
}
-(void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{
if([super respondsToSelector:@selector(scrollViewDidEndDragging:)]) [super scrollViewDidEndDragging:scrollView willDecelerate:decelerate];
MKCoordinateRegion currentRegion = self.region;
bool changeRegionLong = YES;
bool changeRegionLat = YES;
// LONGITUDE
if((currentRegion.center.longitude - (currentRegion.span.longitudeDelta/2)) < self.topLeftCoordinate.longitude) {
currentRegion.center.longitude = (topLeftCoordinate.longitude + (currentRegion.span.longitudeDelta/2));
} else if((currentRegion.center.longitude + (currentRegion.span.longitudeDelta/2)) > self.bottomRightCoordinate.longitude) {
currentRegion.center.longitude = (bottomRightCoordinate.longitude - (currentRegion.span.longitudeDelta/2));
} else {
changeRegionLong = NO;
}
// LATITUDE
if((currentRegion.center.latitude + (currentRegion.span.latitudeDelta/2)) > self.topLeftCoordinate.latitude) {
currentRegion.center.latitude = (topLeftCoordinate.latitude - (currentRegion.span.latitudeDelta/2));
} else if((currentRegion.center.latitude - (currentRegion.span.latitudeDelta/2)) < self.bottomRightCoordinate.latitude) {
currentRegion.center.latitude = (bottomRightCoordinate.latitude + (currentRegion.span.latitudeDelta/2));
} else {
changeRegionLat = NO;
}
if(changeRegionLong || changeRegionLat) [self setRegion:currentRegion animated:YES];
}
-(void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView{
[scrollView setContentOffset:scrollView.contentOffset animated:YES];
}
@end
After trying different ways of limited MKMapView I've concluded that using mapDidChange, and resetting if you're center point goes outside of the boundaries works best, with animated: YES
Here's how I do it (Using the New Zealand lat/Long span/center).
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated{
if ((mapView.region.span.latitudeDelta > 15.589921 ) || (mapView.region.span.longitudeDelta > 175.836914) ) {
CLLocationCoordinate2D centerCoord = CLLocationCoordinate2DMake(-41.162114, 172.836914);
MKCoordinateSpan spanOfNZ = MKCoordinateSpanMake(13.589921, 14.062500 );
MKCoordinateRegion NZRegion = MKCoordinateRegionMake(centerCoord, spanOfNZ);
[mapView setRegion: NZRegion animated: YES];
}
if (abs(abs(mapView.region.center.latitude) - 41.162114) > (13.589921 / 2) ) {
CLLocationCoordinate2D centerCoord = CLLocationCoordinate2DMake(-41.162114, 172.836914);
MKCoordinateSpan spanOfNZ = MKCoordinateSpanMake(13.589921, 14.062500 );
MKCoordinateRegion NZRegion = MKCoordinateRegionMake(centerCoord, spanOfNZ);
[mapView setRegion: NZRegion animated: YES];
}
if (abs(abs(mapView.region.center.longitude) - 172.836914) > (14.062500 / 2) ) {
CLLocationCoordinate2D centerCoord = CLLocationCoordinate2DMake(-41.162114, 172.836914);
MKCoordinateSpan spanOfNZ = MKCoordinateSpanMake(13.589921, 14.062500 );
MKCoordinateRegion NZRegion = MKCoordinateRegionMake(centerCoord, spanOfNZ);
[mapView setRegion: NZRegion animated: YES];
}
}