iphone ios objective-c ipad mkmapview

iphone - Evite el desplazamiento en una MKMapView, también cuando se utiliza el zoom



ios objective-c (6)

El scrollEnabled parece ser rompible una vez que el usuario comienza a pellizcar en un MKMapView .

Aún no puede desplazarse con un dedo, pero si se desplaza con dos dedos mientras acerca o aleja la imagen, puede mover el mapa.

Yo he tratado :

  • Subclase de MKMapKit para deshabilitar la vista de desplazamiento dentro de él.
  • Implementación - mapView:regionWillChangeAnimated: para aplicar el centro.
  • Deshabilitando scrollEnabled .

pero sin suerte

¿Alguien puede decirme una manera segura de tener SOLAMENTE zoom en un MKMapView , por lo que el punto central siempre permanece en el medio?


He leído sobre esto antes, aunque en realidad nunca lo he intentado. Eche un vistazo a este artículo sobre un MKMapView con límites. Utiliza dos métodos delegados para verificar si la vista ha sido desplazada por el usuario.

http://blog.jamgraham.com/blog/2012/04/29/adding-boundaries-to-mkmapview

El artículo describe un enfoque que es similar a lo que has intentado, así que, lo siento si ya te has topado con él.


Intenté esto y funciona.

Primero crea una propiedad:

var originalCenter: CLLocationCoordinate2D?

Luego, en regionWillChangeAnimated, compruebe si este evento es causado por un UIPinchGestureRecognizer:

func mapView(mapView: MKMapView, regionWillChangeAnimated animated: Bool) { let firstView = mapView.subviews.first if let recognizer = firstView?.gestureRecognizers?.filter({ $0.state == .Began || $0.state == .Ended }).first as? UIPinchGestureRecognizer { if recognizer.scale != 1.0 { originalCenter = mapView.region.center } } }

Luego, en regionDidChangeAnimated, regrese a la región original si un gesto de pellizco causó el cambio de la región:

func mapView(mapView: MKMapView, regionDidChangeAnimated animated: Bool) { if let center = originalCenter { mapView.setRegion(MKCoordinateRegion(center: center, span: mapView.region.span), animated: true) originalCenter = nil return } // your other code }


Intente implementar –mapView:regionWillChangeAnimated: o –mapView:regionDidChangeAnimated: en el delegado de su vista de mapa para que el mapa siempre esté centrado en su ubicación preferida.


La versión Swift 3.0 de @Paras Joshi responde https://.com/a/11954355/3754976

con una pequeña corrección de animación.

class MapViewZoomCenter: MKMapView { var originalRegion: MKCoordinateRegion! override func awakeFromNib() { self.configureView() } func configureView() { isZoomEnabled = false self.registerZoomGesture() } ///Register zoom gesture func registerZoomGesture() { let recognizer = UIPinchGestureRecognizer(target: self, action:#selector(MapViewZoomCenter.handleMapPinch(recognizer:))) self.addGestureRecognizer(recognizer) } ///Zoom in/out map func handleMapPinch(recognizer: UIPinchGestureRecognizer) { if (recognizer.state == .began) { self.originalRegion = self.region; } var latdelta: Double = originalRegion.span.latitudeDelta / Double(recognizer.scale) var londelta: Double = originalRegion.span.longitudeDelta / Double(recognizer.scale) //set these constants to appropriate values to set max/min zoomscale latdelta = max(min(latdelta, 80), 0.02); londelta = max(min(londelta, 80), 0.02); let span = MKCoordinateSpanMake(latdelta, londelta) self.setRegion(MKCoordinateRegionMake(originalRegion.center, span), animated: false) } }


No tuve mucha suerte con ninguna de estas respuestas. Hacer mi propio pellizco simplemente entró en conflicto demasiado. Me encontré con casos en los que el zoom normal se acercaba más de lo que podía hacer con mi propio pellizco.

Originalmente, intenté como el cartel original hacer algo como:

- (void) mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated { MKCoordinateRegion region = mapView.region; //... // adjust the region.center //... mapView.region = region; }

Lo que encontré fue que eso no tuvo ningún efecto. También descubrí a través de NSLog s que este método se activará incluso cuando configuro la region o centerCoordinate programación. Lo que llevó a la pregunta: "¿No sería lo anterior, si funcionara, sería infinito?"

Así que ahora estoy conjeturando e hipotetizando que mientras el zoom / desplazamiento / rotación del usuario está ocurriendo, MapView de alguna manera suprime o ignora los cambios en la región. Algo sobre el arbitraje hace que el ajuste programático sea impotente.

Si ese es el problema, entonces tal vez la clave es obtener el ajuste de la región fuera de la regionDidChanged: notificación. Y dado que cualquier ajuste provocará otra notificación, es importante que pueda determinar cuándo no se debe ajustar más. Esto me llevó a la siguiente implementación (donde el subject está suministrando la coordenada central que quiero mantener en el medio):

- (void) recenterMap { double latDiff = self.subject.coordinate.latitude self.mapView.centerCoordinate.latitude; double lonDiff = self.subject.coordinate.longitude - self.mapView.centerCoordinate.longitude; BOOL latIsDiff = ABS(latDiff) > 0.00001; BOOL lonIsDiff = ABS(lonDiff) > 0.00001; if (self.subject.isLocated && (lonIsDiff || latIsDiff)) { [self.mapView setCenterCoordinate: self.subject.coordinate animated: YES]; } } - (void) mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated { if (self.isShowingMap) { if (self.isInEdit) { self.setLocationButton.hidden = NO; self.mapEditPrompt.hidden = YES; } else { if (self.subject.isLocated) { // dispatch outside so it will happen after the map view user events are done dispatch_after(DISPATCH_TIME_NOW, dispatch_get_main_queue(), ^{ [self recenterMap]; }); } } } }

La demora en que se desliza hacia atrás puede variar, pero realmente funciona bastante bien. Y permite que la interacción del mapa siga siendo al estilo de Apple mientras está sucediendo.


Puede tratar de manejar los gestos de pellizco usted mismo usando un UIPinchGestureRecognizer :

Primero establezca scrollEnabled y zoomEnabled en NO y cree el reconocedor de gestos:

UIPinchGestureRecognizer* recognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinch:)]; [self.mapView addGestureRecognizer:recognizer];

En el controlador del reconocedor ajuste el MKCoordinateSpan acuerdo con la escala de zoom:

- (void)handlePinch:(UIPinchGestureRecognizer*)recognizer { static MKCoordinateRegion originalRegion; if (recognizer.state == UIGestureRecognizerStateBegan) { originalRegion = self.mapView.region; } double latdelta = originalRegion.span.latitudeDelta / recognizer.scale; double londelta = originalRegion.span.longitudeDelta / recognizer.scale; // TODO: set these constants to appropriate values to set max/min zoomscale latdelta = MAX(MIN(latdelta, 80), 0.02); londelta = MAX(MIN(londelta, 80), 0.02); MKCoordinateSpan span = MKCoordinateSpanMake(latdelta, londelta); [self.mapView setRegion:MKCoordinateRegionMake(originalRegion.center, span) animated:YES]; }

Esto puede no funcionar perfectamente como la implementación de Apple, pero debería resolver su problema.