iOS的 – 如何限制MapView的特定区域?

我有以下问题:

我有一个“绘制地图”(图片),我把它添加到MapView作为一个覆盖。 没有问题,但..我需要限制的地图视图的覆盖区域,所以用户无法滚动/缩放区域以外的地方..但它应该是可以滚动/放大“边界“覆盖 – 意味着我不能禁用缩放/滚动的MapView。

有没有关于这个主题的想法/解决scheme? 使用MapView / -Kit的原因是我需要添加各种兴趣点到自定义地图。 当使用ImageView + ScrollView呈现自定义地图时,这可能会变得更加复杂。

我已经研究了这个话题,但是我没有find一个好的解决scheme。

任何帮助表示赞赏!

最好的问候,基督徒

编辑:这是我们的解决scheme: 您提供一个顶部和一个底部的坐标来限制地图。 (最小)缩放级别也是有限的。 我已经停用减速,你可以反弹一下地图(为了更好的性能/ ux)。 我在叠加层上添加了一个〜1km的灰色边框,这样用户就无法看到google的orignal世界地图了。

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 

通过实施:

-(void) mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated

你应该能够重置区域到你的特定区域。

看看这个答案有一个如何做到这一点的例子。


另一个解决scheme,带来更精确的事件,但更复杂 (我目前正在使用这个成功的另一个需要)是子类MKMapView和重写UIScrollViewDelegate协议。

如果你这样做,一定要像这样调用super实现:

 - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { if ([super respondsToSelector:@selector(scrollViewWillBeginDragging:)]) [super scrollViewWillBeginDragging:scrollView]; // do what you want } 

注意:虽然协议是公开的,但MKMapView实现是未知的,可能与iOS版本不同,因此使用respondsToSelector: before来检查会更安全。 必须调用超级实现,否则Map将无法正常工作

尝试不同的方式有限的MKMapView我已经得出结论,使用mapDidChange,并重新设置,如果你是中心点超出边界效果最好,与animation:是

这是我怎么做的(使用新西兰纬度/长跨度/中心)。

 - (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]; } } 

我知道这是一个相当古老的问题,但为了避免无限循环,你可以尝试这样的事情: https : //stackoverflow.com/a/4126011/1234011

基本上设置一个标志,以防止再次触发callback,如果是你设置的价值。