一旦用户开始捏合 MKMapView ,scrollEnabled
似乎就可以破解。
您仍然无法用一根手指滚动,但如果您在放大和缩小时用两根手指滚动,则可以移动地图。
我试过了:
MKMapKit
进行子类化以禁用其中的滚动视图。mapView:regionWillChangeAnimated:
强制执行中心。scrollEnabled
。但没有运气。
任何人都可以告诉我一个只能放大 MKMapView 的确定方法,所以中心点始终保持在中间位置吗?
答案 0 :(得分:30)
您可以尝试使用UIPinchGestureRecognizer
:
首先将scrollEnabled
和zoomEnabled
设置为NO
并创建手势识别器:
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];
}
这可能不像Apple的实施那样完美,但它应该可以解决您的问题。
答案 1 :(得分:1)
尝试在地图视图的委托中实施–mapView:regionWillChangeAnimated:
或–mapView:regionDidChangeAnimated:
,以便地图始终以您偏好的位置为中心。
答案 2 :(得分:1)
我以前读过这个,虽然我从来没有尝试过。看看这篇关于带边界的MKMapView的文章。它使用两个委托方法来检查用户是否滚动了视图。
http://blog.jamgraham.com/blog/2012/04/29/adding-boundaries-to-mkmapview
这篇文章介绍了一种类似于你尝试过的方法,所以,如果你已经偶然发现它,那就很抱歉。
答案 3 :(得分:1)
我对这些答案中没有任何好运。做我自己的捏只是太矛盾了。我遇到的情况是,正常变焦会比我自己的捏合变焦得更远。
最初,我试图做原始海报,做以下事情:
- (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];
});
}
}
}
}
它向后滑动的延迟可能会有所不同,但它确实很有效。并且让地图互动在发生时保持Apple风格。
答案 4 :(得分:1)
我试过这个并且有效。
首先创建一个属性:
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
}
答案 5 :(得分:1)
@Paras Joshi的Swift 3.0版本回答https://stackoverflow.com/a/11954355/3754976
小动画修复。
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)
}
}