MKAnnotation在长按可拖动之前需要单击

时间:2014-03-25 03:58:29

标签: ios mkmapview mapkit mkannotation mkannotationview

我已经阅读了很多关于MKAnnotation以及您需要如何在子类中实现setCoordinate以及draggable=TRUE以便使整个shebang可拖动的内容。

我的情况是,在我的iOS7专用应用程序中,无论我是否实现setCoordinate,我的注释都是可拖动的...但问题是我需要先点击它(弹出标注附件)然后然后长按它,然后它将悬停在地图上方的空中并可以被拖动。这对用户来说很困惑,因为它与标准地图应用程序中的方式不同。请注意,在地图应用中,长时间点按注释会使其悬停&没有先决条件的拖拽。

我已尝试实施setCoordinate,但这没有任何区别。除此之外,我的注释子类只存储纬度和范围。经度,工作正常。我只是希望它能够在长时间内直接拖拽。

我的View Controller实现MKMapViewDelegate的相关代码。我可以通过在委托方法中添加断点来验证这一点。

- (void)viewDidLoad
{
        [super viewDidLoad];
[mapView setDelegate:self];    
}

-(MKAnnotationView *)mapView:(MKMapView *)mV viewForAnnotation:
(id <MKAnnotation>)annotation {

    MKPinAnnotationView *pinView = nil;
    if(annotation != mapView.userLocation)
    {
        static NSString *defaultPinID = @"pointPin";
        pinView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
        if ( pinView == nil ) {
            pinView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:defaultPinID];
        }
        pinView.pinColor = MKPinAnnotationColorRed;
        if ([annotation isKindOfClass:[SimpleMapAnnotation class]]) {
            SimpleMapAnnotation *simpleMapAnnotation = (SimpleMapAnnotation*)annotation;
            if ([simpleMapAnnotation color]) {
                pinView.pinColor = [simpleMapAnnotation color];
            }
            if (simpleMapAnnotation.moveable) {
                pinView.draggable=TRUE;
                // delete button to remove an annotation
                UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
                [button setImage:[[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"trash" ofType:@"png"]] forState:UIControlStateNormal] ;
                button.frame = CGRectMake(0, 0, 23, 23);
                pinView.rightCalloutAccessoryView = button;
            }
        }
        pinView.canShowCallout = YES;
        pinView.animatesDrop = YES;
    }
    else {
        [mapView.userLocation setTitle:@"I am here"];
    }
    return pinView;
}

- (void)mapView:(MKMapView *)theMapView annotationView:(MKAnnotationView *)view
calloutAccessoryControlTapped:(UIControl *)control{
    if([view.annotation isKindOfClass:[SimpleMapAnnotation class]]){
        SimpleMapAnnotation *annotation = (SimpleMapAnnotation*)view.annotation;

        //remove the point from the database
    //<snip>

        [UIView animateWithDuration:0.3 delay:0.0 options:0 animations:(void (^)(void)) ^{
            //remove the annotation from the map
            view.alpha = 0.0f;
        }
                         completion:^(BOOL finished){
                             [theMapView removeAnnotation:annotation];
                             view.alpha=1.0f;
                         }];

    }
}


- (void)mapView:(MKMapView *)mapView
 annotationView:(MKAnnotationView *)annotationView
didChangeDragState:(MKAnnotationViewDragState)newState
   fromOldState:(MKAnnotationViewDragState)oldState
{
    if (newState == MKAnnotationViewDragStateEnding)
    {
        if ([annotationView.annotation isMemberOfClass:[SimpleMapAnnotation class]]) {
            SimpleMapAnnotation *simpleMapAnnotation = (SimpleMapAnnotation*)annotationView.annotation;
            simpleMapAnnotation.latitude = [NSNumber numberWithDouble:simpleMapAnnotation.coordinate.latitude];
            simpleMapAnnotation.longitude = [NSNumber numberWithDouble:simpleMapAnnotation.coordinate.longitude];
        }
        CLLocationCoordinate2D droppedAt = annotationView.annotation.coordinate;
        NSLog(@"dropped at %f,%f", droppedAt.latitude, droppedAt.longitude);
    }
}

2 个答案:

答案 0 :(得分:5)

要开始拖动MKAnnotationView对象,应首先选择它。这是设计的。

如果您希望在长时间点击后立即开始移动注释视图,则应在将该长按钮的触摸传递到对象之前将selected属性设置为YES

为此,请将MKPinAnnotationView类的后继者设为以下内容:

// MKImmideateDragPinAnnotationView.h
@interface MKImmideateDragPinAnnotationView : MKPinAnnotationView
@end


// MKImmideateDragPinAnnotationView.m
@implementation MKImmideateDragPinAnnotationView

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self setSelected:YES];
    [super touchesBegan:touches withEvent:event];
}

@end

然后在代码MKPinAnnotationView分配中将MKImmideateDragPinAnnotationView课程更改为pinView课程:

-(MKAnnotationView *)mapView:(MKMapView *)mV viewForAnnotation:(id <MKAnnotation>)annotation {
    ...

    if ( pinView == nil ) {
        pinView = [[MKImmideateDragPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:defaultPinID];
    }

    ...

}

您的图钉将在长按时立即开始拖动。并像往常一样在单击时显示标注。

该技巧适用于iOS 6.xx中的任何MKAnnotationView类 - iOS 7.xx。

答案 1 :(得分:0)

我最终使用this solution,这不仅省去了长拖动之前第一次点击的需要,而且在拖动时对用户来说也是非常流畅的感觉并且具有大的可拖动区域。 Azavea在他们的博客here上实施了一些解释。

我在我的应用程序的下一个版本上几乎完成了(着名的最后一句话),它使用了上面的略微修改版本,即它(a)拖动原始版本,(b)允许可点击对注释的操作和(c)特别忽略了对注释的长按,以便在试图拖动时不会因不必要的敲击操作而烦恼。一旦我完成,我计划分叉或分支(我对你在这种情况下所做的事情有点新)上面的github项目来添加该功能。如果我真的很幸运,我也希望能够修复或者至少配置他们在我链接到的博客的第二段中提到的快速刷卡问题。