在MKMapview上移动MKCircle并拖动MKMapview [英] Moving MKCircle on MKMapview and dragging MKMapview

查看:101
本文介绍了在MKMapview上移动MKCircle并拖动MKMapview的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在MKMapView上有一个MKCircle.它是用户可拖动的,但是如果用户将其拖动到圆之外,则地图应该在移动.

I have a MKCircle on MKMapView. It is user-draggable, but if the user drags the area outside the circle, the map should be moving instead.

- (IBAction)createPanGestureRecognizer:(id)sender
{
    _mapView.scrollEnabled=NO;
    _panRecognizer = [[UIPanGestureRecognizer alloc]
                      initWithTarget:self action:@selector(respondToPanGesture:)];
    [_mapView addGestureRecognizer:_panRecognizer];
}

-(void)respondToPanGesture:(UIPanGestureRecognizer*)sender {

    static CGPoint originalPoint;

    if (sender.state == UIGestureRecognizerStateBegan) {
        CGPoint point = [sender locationInView:_mapView];
        CLLocationCoordinate2D tapCoordinate = [_mapView convertPoint:point toCoordinateFromView:_mapView];

        CLLocation *tapLocation = [[CLLocation alloc] initWithLatitude:tapCoordinate.latitude longitude:tapCoordinate.longitude];

        CLLocationCoordinate2D originalCoordinate = [_circle coordinate];
        CLLocation *originalLocation = [[CLLocation alloc] initWithLatitude:originalCoordinate.latitude longitude:originalCoordinate.longitude];

        if ([tapLocation distanceFromLocation:originalLocation] > [_circle radius]) {
            _mapView.scrollEnabled=YES;
            _isAllowedToMove=NO;
        }
        else if ([tapLocation distanceFromLocation:originalLocation] < [_circle radius]) {
            originalPoint = [_mapView convertCoordinate:originalCoordinate toPointToView:sender.view];
            _isAllowedToMove=YES;
        }
    }

    if (sender.state == UIGestureRecognizerStateChanged) {
        if (_isAllowedToMove)
        {
            CGPoint translation = [sender translationInView:sender.view];
            CGPoint newPoint    = CGPointMake(originalPoint.x + translation.x, originalPoint.y + translation.y);

            CLLocationCoordinate2D newCoordinate = [_mapView convertPoint:newPoint toCoordinateFromView:sender.view];

            MKCircle *circle2 = [MKCircle circleWithCenterCoordinate:newCoordinate radius:[_circle radius]];
            [_mapView addOverlay:circle2];
            [_mapView removeOverlay:_circle];
            _circle = circle2;
        }
    }

    if (sender.state == UIGestureRecognizerStateEnded || sender.state == UIGestureRecognizerStateFailed || sender.state == UIGestureRecognizerStateCancelled) {
        _mapView.scrollEnabled=NO;
        _isAllowedToMove=NO;
    }
}

拖动圆圈效果很好,但是在尝试拖动地图时,它会保持静止. 我的假设是

Dragging the circle works fine, but when trying to drag the map, it stays still. My assumption is that

_mapView.scrollEnabled=YES;

使地图可拖动,但是它需要另一个拖动手势才能开始. 如何做到这一点而又不失去移动圆环的能力?

makes the map draggable, but it needs another drag gesture to be started. How to accomplish this without losing the ability to move the circle?

推荐答案

如果用户开始将其拖动到圆圈外,则可以拖动地图(如果没有,则拖动地图到用户开始在圆圈中拖动 ),请勿从一开始就禁用scrollEnabled -请将其保留(直到拖动 starts ,我们可以决定是否禁用或不是).

To make it so that the map can be dragged if the user starts dragging outside the circle (and to not drag the map if the user starts dragging inside the circle), don't disable scrollEnabled from the beginning -- leave it on (until dragging starts and we can decide whether to disable or not).

为了最初保留scrollEnabled(即让地图进行自己的平移)以添加我们自己的手势识别器,我们需要实现shouldRecognizeSimultaneouslyWithGestureRecognizer并返回YES.

In order to leave scrollEnabled on initially (ie. let the map do its own panning) and to add our own gesture recognizer, we'll need to implement shouldRecognizeSimultaneouslyWithGestureRecognizer and return YES.

更新后的createPanGestureRecognizer:看起来像这样:

The updated createPanGestureRecognizer: would look like this:

- (IBAction)createPanGestureRecognizer:(id)sender
{
    //_mapView.scrollEnabled=NO;  // <-- do NOT disable scrolling here
    _panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(respondToPanGesture:)];
    _panRecognizer.delegate = self;  // <-- to implement shouldRecognize
    [_mapView addGestureRecognizer:_panRecognizer];
}

-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    return YES;
}

然后在手势处理程序中,当手势开始时,根据平移开始的位置(圆圈的外部或内部)启用或禁用scrollEnabled:

Then in our gesture handler, when the gesture begins, enable or disable scrollEnabled based on where the pan starts (outside or inside the circle):

if ([tapLocation distanceFromLocation:originalLocation] > [_circle radius]) {
    _mapView.scrollEnabled=YES;
    _isAllowedToMove=NO;
}
else //if ([tapLocation distanceFromLocation:originalLocation] < [_circle radius]) {
//NOTE: It's not really necessary to check if distance is less than radius
//      in the ELSE part since in the IF we checked if it's greater-than.
//      If we get to the ELSE, we know distance is <= radius.
//      Unless for some reason you want to handle the case where
//      distance exactly equals radius differently but this is unlikely.
{
    originalPoint = [_mapView convertCoordinate:originalCoordinate toPointToView:sender.view];
    _mapView.scrollEnabled=NO;  // <-- disable scrolling HERE
    _isAllowedToMove=YES;
}

最后,始终在手势结束时重新启用scrollEnabled(以防万一).
当下一个手势开始时,如有必要,它将被重新禁用:

Finally, always re-enable scrollEnabled when a gesture ends (just in case).
When the next gesture starts, it will be re-disabled if necessary:

if (sender.state == UIGestureRecognizerStateEnded || sender.state == UIGestureRecognizerStateFailed || sender.state == UIGestureRecognizerStateCancelled) {
    _mapView.scrollEnabled=YES;  // <-- enable instead of disable
    _isAllowedToMove=NO;
}

请注意,如果允许用户多次调用createPanGestureRecognizer:,则您可能应该将识别器的创建和添加移动到其他位置(可能是viewDidLoad),否则会将多个实例添加到地图中.

Note that if the user is allowed to call createPanGestureRecognizer: multiple times, you should probably move the creation and addition of the recognizer somewhere else (viewDidLoad maybe) otherwise multiple instances will get added to the map.

或者,将按钮更改为切换按钮,以便在移动"模式为开"的情况下,它从地图上删除手势识别器,而不是创建和添加手势识别器.

Alternatively, change the button to a toggle so that if "move" mode is ON, it removes the gesture recognizer from the map instead of creating and adding it.

这篇关于在MKMapview上移动MKCircle并拖动MKMapview的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆