2011-04-15 4 views
14

Tengo el siguiente problema:iOS - ¿Cómo limitar el MapView a una región específica?

Tengo un "mapa dibujado" (imagen) que agrego a MapView como una Superposición. No hay problema con eso ... pero tengo que limitar el MapView a la región de la Superposición, por lo que un usuario no puede desplazarse/alejarse fuera de esta región ... pero debería ser posible desplazarse/acercarse a los "límites". "de la superposición" significa que no puedo deshabilitar el zoom/desplazamiento para MapView.

¿Hay alguna idea/solución sobre este tema? La razón para usar MapView/-Kit es que necesito agregar varios POI al mapa personalizado. Esto puede volverse más complejo cuando solo se usa ImageView + ScrollView para presentar el mapa personalizado.

Investigué mucho sobre este tema, pero no encontré una buena solución.

¡Se agradece cualquier ayuda!

Best Regards, cristianos

Editar: Esta es nuestra solución: usted proporciona un superior izquierda y una parte inferior derecha se coordinan para limitar el mapa. El nivel de zoom (mínimo) también es limitado. Desactivé la desaceleración y puedes saltar un poco fuera del mapa (para un mejor rendimiento/ux). Agregué un borde gris de ~ 1km a la superposición para que el usuario no pueda ver el mapa mundial orignal de 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 
+0

añade mi solución. – cweinberger

+0

Gracias por actualizar con la solución. Solo quería limitar el zoom máximo, y me encontré con un problema w/usando simplemente scrollViewDidZoom: a cualquier persona que esté por ahí, asegúrese de establecer su nuevo lapso en MENOS que el intervalo de verificación if, de lo contrario, la vista de mapa se atascaría al máximo enfocar. – Andrew

+0

Una mejor solución escrita para swift está allí http://stackoverflow.com/a/31799617/2814964 – cl3m

Respuesta

6

Mediante la implementación:

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

Debería poder restablecer la región a su región específica.

Mire at that answer para tener un ejemplo de cómo hacerlo.


Otra solución, que trae eventos más precisos pero es más complejo(estoy actualmente el uso de este éxito para otra necesidad) es a subclase MKMapView y anular UIScrollViewDelegate protocolo.

Si lo hace, asegúrese de llamar super aplicación de esa manera:

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

Nota: Mientras que el protocolo es pública, MKMapView aplicación es desconocida y puede diferir con las versiones de iOS, por lo que es más segura para verificar con respondsToSelector: antes. Usted debe llamar super implementaciones o el mapa simplemente no funcionará correctamente.

+0

Hmm .. Creo que este delegado se disparará cuando empiece a mover el mapa. Desafortunadamente, en este momento no sé qué hará el usuario con el mapa (podría ser un gesto válido de zoom/desplazamiento). Y el '- (void) mapView: (MKMapView *) mapView regionWillChangeAnimated: (BOOL) animated' se dispara demasiado tarde. ¿O estoy totalmente equivocado con esto? – cweinberger

+0

agregó otra solución que podría ayudar;) –

+0

gracias! suena bien, lo intentaré :) – cweinberger

13

Después de probar diferentes maneras de MKMapView limitada he concluido que el uso de mapDidChange, y restablecer si estás centro de punto va fuera de los límites funciona mejor, con animada: SÍ

Así es como lo hago (Uso el lat de Nueva Zelanda/Palmo largo/centro).

- (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

Debo mencionar que el código anterior también tiene un límite en el nivel de acercamiento. –

+0

Para cualquier otra persona que intente hacer que esto funcione, este es definitivamente el camino a seguir. – Undistraction

+0

Esto se convirtió en una recursión infinita para mí. Tuve que desconectar el delegado del mapa del NIB y configurar el delegado en 'viewDidLoad' después de establecer la región inicial. – Mazyod

0

Sé que esto es una pregunta bastante viejo, pero para evitar el bucle infinito que podría intentar algo como esto: https://stackoverflow.com/a/4126011/1234011

establecer Básicamente una bandera para evitar la devolución de llamada se dispare de nuevo si fue usted quien establecer el valor

  • Ken
Cuestiones relacionadas