限制MKMapView滚动

mag*_*725 10 iphone scroll overlay map mkmapview

我想自定义图像添加到MKMapView作为一个MKOverlayView-我需要从能够覆盖的范围之外滚动限制用户.有没有现成的功能呢?还是其他任何建议?

谢谢,马特

小智 19

如果你只是想在覆盖冻结地图视图,你可以在地图视图的区域设置为叠加层的边界,并设置scrollEnabledzoomEnabledNO.

但这不会让用户在叠加层的边界内滚动或缩放.

没有内置的方法将地图视图限制为叠加层的边界,因此您必须手动执行此操作.首先,确保您的MKOverlay对象实现该boundingMapRect属性.然后可以在regionDidChangeAnimated委托方法中使用它来根据需要手动调整视图.

这是一个如何做到这一点的例子.
下面的代码应该在具有的代码中MKMapView.
确保地图视图最初设置为可以显示叠加层的区域.

//add two ivars to the .h...
MKMapRect lastGoodMapRect;
BOOL manuallyChangingMapRect;

//in the .m...
- (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated
{
    if (manuallyChangingMapRect)
        return;     
    lastGoodMapRect = mapView.visibleMapRect;
}

- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
{
    if (manuallyChangingMapRect) //prevents possible infinite recursion when we call setVisibleMapRect below
        return;     

    // "theOverlay" below is a reference to your MKOverlay object.
    // It could be an ivar or obtained from mapView.overlays array.

    BOOL mapContainsOverlay = MKMapRectContainsRect(mapView.visibleMapRect, theOverlay.boundingMapRect);

    if (mapContainsOverlay)
    {
        // The overlay is entirely inside the map view but adjust if user is zoomed out too much...
        double widthRatio = theOverlay.boundingMapRect.size.width / mapView.visibleMapRect.size.width;
        double heightRatio = theOverlay.boundingMapRect.size.height / mapView.visibleMapRect.size.height;
        if ((widthRatio < 0.6) || (heightRatio < 0.6)) //adjust ratios as needed
        {
            manuallyChangingMapRect = YES;
            [mapView setVisibleMapRect:theOverlay.boundingMapRect animated:YES];
            manuallyChangingMapRect = NO;
        }
    }
    else
        if (![theOverlay intersectsMapRect:mapView.visibleMapRect])
        {
            // Overlay is no longer visible in the map view.
            // Reset to last "good" map rect...
            [mapView setVisibleMapRect:lastGoodMapRect animated:YES];
        }   
}
Run Code Online (Sandbox Code Playgroud)

我尝试使用内置MKCircle叠加层,似乎运行良好.


编辑:

它在95%的时间内都能很好地工作,但是,我通过一些测试证实它可能在两个位置之间振荡,然后进入无限循环.所以,我编辑了一下,我认为这应该解决问题:

// You can safely delete this method:
- (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated {

}

- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
     // prevents possible infinite recursion when we call setVisibleMapRect below
    if (manuallyChangingMapRect) {
        return;
    }

    // "theOverlay" below is a reference to your MKOverlay object.
    // It could be an ivar or obtained from mapView.overlays array.

    BOOL mapContainsOverlay = MKMapRectContainsRect(mapView.visibleMapRect, theOverlay.boundingMapRect);

    if (mapContainsOverlay) {
        // The overlay is entirely inside the map view but adjust if user is zoomed out too much...
        double widthRatio = theOverlay.boundingMapRect.size.width / mapView.visibleMapRect.size.width;
        double heightRatio = theOverlay.boundingMapRect.size.height / mapView.visibleMapRect.size.height;
        // adjust ratios as needed
        if ((widthRatio < 0.6) || (heightRatio < 0.6)) {
            manuallyChangingMapRect = YES;
            [mapView setVisibleMapRect:theOverlay.boundingMapRect animated:YES];
            manuallyChangingMapRect = NO;
        }
    } else if (![theOverlay intersectsMapRect:mapView.visibleMapRect]) {
        // Overlay is no longer visible in the map view.
        // Reset to last "good" map rect...
        manuallyChangingMapRect = YES;
        [mapView setVisibleMapRect:lastGoodMapRect animated:YES];
        manuallyChangingMapRect = NO;
    } else {
        lastGoodMapRect = mapView.visibleMapRect;
    }
}
Run Code Online (Sandbox Code Playgroud)

如果有人正在寻找快速MKOverlay解决方案,这里有一个:

- (void)viewDidLoad {
    [super viewDidLoad];

    MKCircle* circleOverlay = [MKCircle circleWithMapRect:istanbulRect];
    [_mapView addOverlay:circleOverlay];

    theOverlay = circleOverlay;
}

- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id<MKOverlay>)overlay {
    MKCircleView* circleOverlay = [[MKCircleView alloc] initWithCircle:overlay];
    [circleOverlay setStrokeColor:[UIColor mainColor]];
    [circleOverlay setLineWidth:4.f];

    return circleOverlay;
}
Run Code Online (Sandbox Code Playgroud)

  • @AnnaKarenina您的代码非常棒,特别是因为评论非常好.但是,有些情况下你会错过并导致代码在位置之间振荡,然后进行无限循环(有点像特技,如果你问我).所以,我将添加我的代码,如果你觉得它很有用,请将它与你的代码合并. (2认同)