Tengo el siguiente problema:

Tengo un «mapa dibujado» (imagen), que me agregue a la MapView como una Superposición. No hay Problema con eso.. pero necesito limitar el MapView para la región de la Superposición, de modo que un usuario no es capaz de desplazamiento/zoom fuera de esta región.. pero debe ser posible desplazamiento/zoom dentro de los «límites» de la superposición – significa que no se puede simplemente desactivar zoom/desplazamiento para la MapView.

Hay alguna idea/solución sobre este tema? La razón de usar el MapView/-Kit es que necesito agregar varios lugares de interés en el mapa personalizado. Esto puede ser más complejo cuando sólo el uso de un ImageView+ScrollView para presentar el mapa personalizado.

Yo he investigado mucho sobre este tema, pero no me pareció una buena solución.

Cualquier ayuda es muy apreciada.

Saludos
Cristiano

Edit: Esta es nuestra solución:
Suministrar un topleft y un bottomright coordinar para limitar el mapa. El (mínimo) zoomlevel también es limitado. He desactivado la desaceleración y que son capaces de rebotar un poco fuera del mapa (para un mejor rendimiento/ux). He añadido un ~1km borde gris a la superposición de manera que el usuario isnÄt capaz de ver el orignal mundo 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
añadido mi solución.
Gracias por la actualización con la solución. Yo sólo quería límite de zoom máximo, y se topó con un poco de un problema w/ usar sólo scrollViewDidZoom: A nadie más ahí fuera, asegúrese de que establece la nueva estructura a MENOS que el si de verificación abarcan de lo contrario la mapview se ubicará en el máximo del zoom.
Una mejor solución para swift es no stackoverflow.com/a/31799617/2814964

OriginalEl autor cweinberger | 2011-04-15

3 Comentarios

  1. 6

    Mediante la implementación de :

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

    Usted debe ser capaz de restablecer la región para su aplicación específica.

    Mirada a esa respuesta para tener un ejemplo de cómo hacer esto.


    Otra solución, que trae más precisa de los eventos, pero es más complejo (actualmente estoy usando con éxito para otra necesidad) es subclase MKMapView y reemplazar UIScrollViewDelegate protocolo.

    Si lo hace, asegúrese de llamar super la implementación como que :

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

    Nota: Mientras que el protocolo es público, MKMapView aplicación es desconocido y puede variar con las versiones de iOS, así que es más seguro para comprobar con respondsToSelector: antes. Usted debe llamada super implementaciones o Mapa no sólo el trabajo correctamente.

    Hmm.. creo que este delegado del fuego cuando comience a mover el Mapa. Unfortunalety en este momento no sé lo que el usuario va a hacer con el Mapa (podría ser un válido zoom/desplazamiento gesto). Y el -(void) mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated incendios demasiado tarde. O estoy totalmente equivocado con esto?!
    añadido otra solución que podría ayudar 😉
    gracias! suena bonito, va a darle una oportunidad 🙂
    que no es tan agradable, sucio «hacking» un poco algunas apis que no son lo suficientemente abierta para ciertos usos… aah si sólo apple y google todavía estaban amigos podríamos tener un destacado y estable MapKit
    en este caso, cualquier cosa que trabajar y buscar aceptar (para el usuario final), es una solución agradable para mí. pero tienes razón… hay definitivamente debe ser un método incluido para limitar la región visible :/

    OriginalEl autor Vincent Guerci

  2. 13

    Después de probar diferentes maneras de limitada MKMapView he llegado a la conclusión de que el uso de mapDidChange, y reajustar si estás centro de punto va fuera de los límites que mejor funciona, con animados: SÍ

    He aquí cómo lo hago (el Uso de la Nueva Zelanda lat/Long span/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];
    }
    }
    Debo mencionar el código de arriba también tiene un límite en el nivel de zoom.
    Para cualquier persona tratando de conseguir que esto funcione, este es definitivamente el camino a seguir.
    Esto se convirtió en una recursividad infinita para mí. Tuve que desactivar el mapa delegado de la PUNTA, y establecer el delegado en viewDidLoad después de la configuración inicial de la región.
    Gracias por esta solución. Pequeña nota – Si alguien más tiene problemas con esto en el futuro he tenido que cambiar de abs(x) fabs(x) como lon/lats dobles y abs(x) devuelve un int. Esto no parece importar con los valores que tiene como son tan grandes, pero yo estaba trabajando con mucho a las regiones más pequeñas!
    Mientras esto definitivamente ha trabajado para mí (y que han recibido mi upvote) es demasiado detallado y hay una función de valor absoluto. (Hacer uso de fabs(x) como @bean señalado). He creado un más legible esencial para cualquier persona interesada: gist.github.com/Alp-Phone/e11cca67e77285566d4d

    OriginalEl autor mrdavenz

  3. 0

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

    Básicamente establecer un indicador para evitar la devolución de llamada de disparar de nuevo si fue usted quien establece el valor.

    • Ken

    OriginalEl autor Ken Koch

Dejar respuesta

Please enter your comment!
Please enter your name here