防止在MKMapView中滚动,同样在缩放时

一旦用户开始捏在MKMapView中 scrollEnabled似乎是易碎的。

您仍然无法用一根手指滚动,但如果在放大和缩小时用两个手指滚动,则可以移动地图。

我努力了 :

  • MKMapKit以禁用其内的滚动视图。
  • 实现 – mapView:regionWillChangeAnimated:执行中心。
  • 禁用scrollEnabled

但没有运气。

谁能告诉我一个肯定的方法,只有放大MKMapView ,所以中心点始终停留在中间?

您可以尝试使用UIPinchGestureRecognizer自己处理捏手势:

首先将scrollEnabledzoomEnabled设置为NO并创build手势识别器:

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

在识别器处理程序中,根据缩放比例调整MKCoordinateSpan

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

这可能无法像苹果的实施完美,​​但它应该解决您的问题。

尝试在地图视图的代表中实现–mapView:regionWillChangeAnimated:–mapView:regionDidChangeAnimated:以便地图总是居中您的首选位置。

我以前读过这个,虽然我从来没有尝试过。 看看这篇关于带有边界的MKMapView的文章。 它使用两个委托方法来检查视图是否被用户滚动。

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

这篇文章描述了一种类似于你所尝试的方法,所以,如果你已经偶然发现了这个方法,对不起。

这些答案我没有太多的运气。 做我自己的捏只是冲突太多。 我遇到的情况是,正常的缩放比我自己的捏还要大。

本来,我试图作为原始的海报做类似的事情:

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

我发现那是没有效果的。 我也通过NSLog发现,即使我以编程方式设置regioncenterCoordinate ,该方法也会触发。 这导致了这样一个问题:“如果DID工作无限,那么上面不是这样吗?

所以我现在猜测和假设,当用户缩放/滚动/旋转正在发生时,MapView以某种方式抑制或忽略对区域的改变。 有关仲裁的事情使程序调整变得无能为力。

如果这是问题,那么也许关键是要获得regionDidChanged:通知之外的区域调整。 而且由于任何调整都会触发另一个通知,因此重要的是它能够确定何时不再调整。 这导致我下面的实现(其中subject是提供我想停留在中间的中心坐标):

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

它滑回的延迟可能会有所不同,但它确实工作得很好。 让地图互动在发生的时候保持苹果风格。

我试过这个,它的工作原理。

首先创build一个属性:

 var originalCenter: CLLocationCoordinate2D? 

然后在regionWillChangeAnimated中,检查这个事件是否由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 } } } 

然后在regionDidChangeAnimated中,如果捏合手势导致区域改变,则返回到原始区域:

 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 } 

Swift 3.0版本的@Paras Joshi回答https://stackoverflow.com/a/11954355/3754976

与小animation修复。

 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) } }