防止在MKMapView中滚动,同样在缩放时
一旦用户开始捏在MKMapView中 scrollEnabled
似乎是易碎的。
您仍然无法用一根手指滚动,但如果在放大和缩小时用两个手指滚动,则可以移动地图。
我努力了 :
-
MKMapKit
以禁用其内的滚动视图。 - 实现 –
mapView:regionWillChangeAnimated:
执行中心。 - 禁用
scrollEnabled
。
但没有运气。
谁能告诉我一个肯定的方法,只有放大MKMapView ,所以中心点始终停留在中间?
您可以尝试使用UIPinchGestureRecognizer
自己处理捏手势:
首先将scrollEnabled
和zoomEnabled
设置为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
发现,即使我以编程方式设置region
或centerCoordinate
,该方法也会触发。 这导致了这样一个问题:“如果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) } }