iOS - Как ограничить MapView для конкретного региона? - PullRequest
17 голосов
/ 15 апреля 2011

У меня следующая проблема:

У меня есть «нарисованная карта» (изображение), которую я добавляю в MapView в качестве наложения.Никаких проблем с этим ... но мне нужно ограничить MapView областью наложения, чтобы пользователь не мог прокручивать / масштабировать за пределами этой области ... но должна быть возможность прокручивать / масштабировать внутри "границ""наложения - означает, что я не могу просто отключить масштабирование / прокрутку для MapView.

Есть ли какие-либо идеи / решения по этой теме?Причина использования MapView / -Kit заключается в том, что мне нужно добавить различные POI к пользовательской карте.Это может стать более сложным, когда просто использовать ImageView + ScrollView для представления пользовательской карты.

Я много исследовал эту тему, но не нашел хорошего решения.

Любойпомощь приветствуется!

С наилучшими пожеланиями, Кристиан

Редактировать: Это наше решение: Вы предоставляете координаты топ-лефт и нижнюю правую, чтобы ограничить карту.(Минимальный) уровень масштабирования также ограничен.Я отключил замедление, и вы можете немного отскочить от карты (для лучшей производительности / UX).Я добавил серую рамку размером ~ 1 км, чтобы пользователь не мог видеть оригинальную карту мира 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

Ответы [ 3 ]

13 голосов
/ 27 мая 2011

Попробовав различные способы ограниченного 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];
  }
}
6 голосов
/ 15 апреля 2011

Реализуя:

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

Вы должны иметь возможность сбросить регион на ваш конкретный.

Посмотрите на этот ответ , чтобы получить пример того, как это сделать.


Другое решение, которое приносит более точные события, но более сложное (в настоящее время я успешно использую это для другой необходимости) для подкласса MKMapView и переопределить UIScrollViewDelegate протокол.

Если вы сделаете это, обязательно вызовите реализацию super следующим образом:

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

Примечание. Хотя протокол является общедоступным, реализация MKMapView неизвестна и может отличаться в зависимости от версии iOS, поэтому более безопасно проверить с помощью respondsToSelector: перед этим. Вы должны вызвать супер реализации или Карта просто не будет работать правильно .

0 голосов
/ 01 мая 2013

Я знаю, что это довольно старый вопрос, но чтобы избежать бесконечного цикла, вы можете попробовать что-то вроде этого: https://stackoverflow.com/a/4126011/1234011

По сути, установите флаг, чтобы предотвратить повторный запуск обратного вызова, если это выустановить значение.

  • Кен
...