2011-04-15 75 views
14

我有以下問題:iOS - 如何限制MapView到特定區域?

我有一個「繪製的地圖」(圖片),我將它添加到MapView作爲覆蓋。沒有問題,但..我需要將地圖視圖限制到疊加區域,所以用戶無法在此區域之外滾動/縮放......但應該可以在「邊界」內滾動/縮放「的覆蓋 - 意味着我不能禁用縮放/滾動的MapView。

有沒有關於這個主題的任何想法/解決方案?使用MapView/-Kit的原因是我需要將各種POI添加到自定義地圖。當使用ImageView + ScrollView呈現自定義地圖時,這可能會變得更加複雜。

我已經研究了很多關於這個話題,但我沒有找到一個很好的解決方案。

任何幫助表示讚賞!

最好的問候, 基督教

編輯:這是我們的解決方案: 您提供的左上和bottomright協調,以限制地圖。 (最小)縮放級別也是有限的。我已經停用了減速功能,並且您可以從地圖中反彈一下(以獲得更好的性能/ ux)。我在疊加層上添加了1公里左右的灰色邊框,因此用戶無法看到谷歌的原始世界地圖。

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 
+0

加入我的解決方案。 – cweinberger 2011-04-22 12:59:12

+0

感謝您使用解決方案進行更新。我只是想限制最大縮放,並且使用scrollViewDidZoom時遇到了一些問題:對於其他任何人,確保將新跨度設置爲小於if檢查跨度,否則mapview將卡住在max放大。 – Andrew 2011-06-17 15:38:15

+0

爲swift提供了一個更好的書面解決方案http://stackoverflow.com/a/31799617/2814964 – cl3m 2015-09-23 14:15:50

回答

6

通過實施:

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

您應該能夠將區域重置爲您的特定區域。

at that answer有如何做到這一點的例子。


另一種解決方案,帶來更精確的事件,但(我目前使用這種成功的另一個必要)更復雜是繼承MKMapView和覆蓋UIScrollViewDelegate協議。

如果你這樣做,請確保調用super實現這樣的:

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

注:雖然該協議是公開的,MKMapView實現是未知的,可能會與iOS版本不同,所以它更安全以前用respondsToSelector:進行檢查。你必須調用超級實現或地圖將只是不能正常工作

+0

嗯..我認爲這個代表會在我開始移動Map時觸發。此時不幸,我不知道用戶將如何處理地圖(可能是有效的縮放/滾動手勢)。並且' - (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated'太晚了。或者我完全錯了嗎?! – cweinberger 2011-04-16 11:09:28

+0

增加了另一個可能有幫助的解決方案;) – 2011-04-16 12:44:58

+0

謝謝!聽起來不錯,會給它一個嘗試:) – cweinberger 2011-04-16 12:46:10

13

嘗試有限的MKMapView的不同方式後,我已經得出結論,使用mapDidChange和重置,如果你是中心點去邊界之外的效果最好,與動畫:是

這裏是我如何做到這一點(使用新西蘭經/長跨度/中心)。

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

我應該提到上面的代碼也對縮放級別有限制。 – 2011-05-27 03:00:43

+0

對於其他人試圖讓這個工作,這絕對是要走的路。 – Undistraction 2012-06-13 11:34:53

+0

這變成了一個無限的遞歸給我。我必須從NIB中取消映射委託,並在設置初始區域後在'viewDidLoad'中設置委託。 – Mazyod 2012-12-29 04:50:34

0

我知道這是一個很老的問題,但要避免無限循環,你可以嘗試這樣的事:https://stackoverflow.com/a/4126011/1234011

基本上設置一個標誌,以防止回調再次射擊,如果它是你是誰設置值。