如何从通过 MKAnnotationView 添加的按钮获取点击事件

Posted

技术标签:

【中文标题】如何从通过 MKAnnotationView 添加的按钮获取点击事件【英文标题】:How to get click event from a button added over MKAnnotationView 【发布时间】:2011-08-04 12:12:36 【问题描述】:

任何人都知道是否有办法从添加到MKAnnotationViewbutton 获取点击事件,这个button 用作标签只是为了显示map 上每个引脚的名称,现在我单击pin 时成功显示自定义view(包含图像、文本...),因此单击按钮(标签)时我需要做同样的事情。

感谢您提供的任何建议。

buttonMKAnnotationView 中的代码:

UIButton * pinButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 140, 28)];
[pinButton.titleLabel setTextColor:[UIColor colorWithRed:255/255.0 green:255/255.0 blue:255/255.0 alpha:1]]; 
[pinButton setCenter:CGPointMake(pinAnnotationView.center.x + 70, pinAnnotationView.center.y + 10)]; 
[pinButton addTarget:self action:@selector(pinLabelClicked) forControlEvents:UIControlEventTouchUpInside]; 
[pinAnnotationView addSubView:pinButton]; 
[pinButton setUserInteractionEnabled:YES];

【问题讨论】:

你是如何创建按钮的? MKAnnotationView中没有按钮,基本上你在触摸MKAnnotationView 【参考方案1】:

标准的 UI 方法是使用标注视图并添加一个附件按钮,如 progrmr 所示。

但是,如果您必须将按钮直接添加到MKAnnotationView,您的方法的问题是MKPinAnnotationView 的默认框架(不能轻易更改)小于您的按钮添加因此大多数按钮将不会响应触摸,即使您切换到使用 MKAnnotationView 并增加帧大小,MKMapView 也会阻止按钮获得任何触摸。

您需要做的是向按钮添加UITapGestureRecognizer(使用手势处理程序的操作方法而不是按钮上的addTarget)并将按钮添加到具有适当帧大小的普通MKAnnotationView MKPinAnnotationView.

例子:

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

    MKAnnotationView *annView = (MKAnnotationView *)[mapView 
            dequeueReusableAnnotationViewWithIdentifier: @"pin"];
    if (annView == nil)
    
        annView = [[[MKAnnotationView alloc] initWithAnnotation:annotation 
                      reuseIdentifier:@"pin"] autorelease];

        annView.frame = CGRectMake(0, 0, 200, 50);

        UIButton *pinButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        pinButton.frame = CGRectMake(0, 0, 140, 28);
        pinButton.tag = 10;

        UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] 
            initWithTarget:self action:@selector(handlePinButtonTap:)];
        tap.numberOfTapsRequired = 1;
        [pinButton addGestureRecognizer:tap];
        [tap release];

        [annView addSubview:pinButton]; 
    

    annView.annotation = annotation;

    UIButton *pb = (UIButton *)[annView viewWithTag:10];
    [pb setTitle:annotation.title forState:UIControlStateNormal];

    return annView;


- (void) handlePinButtonTap:(UITapGestureRecognizer *)gestureRecognizer 

    UIButton *btn = (UIButton *) gestureRecognizer.view;
    MKAnnotationView *av = (MKAnnotationView *)[btn superview];
    id<MKAnnotation> ann = av.annotation;
    NSLog(@"handlePinButtonTap: ann.title=%@", ann.title);

请注意,这将阻止地图视图的 didSelectAnnotationView 委托方法触发。如果您需要触发该方法(在 addition 到按钮的手势处理程序方法中),请添加以下内容:

//in the view controller's interface:
@interface YourVC : UIViewController <UIGestureRecognizerDelegate>

//where the UITapGestureRecognizer is created:
tap.delegate = self;

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer 
        shouldRecognizeSimultaneouslyWithGestureRecognizer
            :(UIGestureRecognizer *)otherGestureRecognizer

    return YES;

【讨论】:

感谢您的回复,它非常有用,但是我只想知道在这种情况下如何添加引脚?? 不确定你的意思。可以通过调用 addAnnotation 像往常一样添加注释。你的意思是如何获取默认的“pin”图片? 我说的是必须连接到每个按钮(标签)的引脚(图标)。 在 viewForAnnotation 中,您必须使用您自己的图像执行annView.image = your-UIImage;(或者您可以创建一个 UIImageView 并将Subview 添加到 annView)。 This answer 有一些您可以使用的默认图钉图片。 好的,非常感谢,现在我明白你的意思了,不值得使用 MKPinAnnotationView。【参考方案2】:

我使用此代码(为清楚起见而减少了)向标注视图(在我的应用程序中)添加了一个按钮:

-(MKAnnotationView *)mapView:(MKMapView *)map 
        viewForAnnotation:(StationItem*)annotation

    static NSString *AnnotationViewID = @"stationViewId";

    if ([annotation isKindOfClass:[MKUserLocation class]]) 
        return nil;  // use default user location view
    

    MKPinAnnotationView *annotationView = 
        (MKPinAnnotationView*) [mapView dequeueReusableAnnotationViewWithIdentifier:AnnotationViewID];

    if (annotationView == nil) 
        // if an existing pin view was not available, create one
        annotationView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:AnnotationViewID] autorelease];

        // add rightAccessoryView
        UIButton* aButton = [UIButton buttonWithFrame:CGRectMake(0, 0, 75, 30)];
        [aButton setTitle:@"Directions" forState:UIControlStateNormal];
        annotationView.rightCalloutAccessoryView = aButton;
    

    annotationView.annotation = annotation;
    annotationView.canShowCallout = YES;
    annotationView.animatesDrop   = NO;

    return annotationView;

完成此操作后,您需要实现 MKMapViewDelegate 以在点击按钮时处理对委托的回调:

- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control

【讨论】:

谢谢,但我不能使用 rightCalloutAccessoryView,因为我禁用了 canShowCallout,让点击图钉只显示我创建的自定义视图。【参考方案3】:

尝试将触摸传递给子视图:

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 
 [pinButton touchesEnded:touches withEvent:event];

如果你的 buttonView 在前面,我很惊讶你有问题?尝试确保它是: [self bringSubviewToFront:pinButton];

【讨论】:

该按钮出现在图钉附近,但无法点击我尝试bringSubviewToFront 但没有结果。

以上是关于如何从通过 MKAnnotationView 添加的按钮获取点击事件的主要内容,如果未能解决你的问题,请参考以下文章

Swift - 将 MKAnnotationView 添加到 MKMapView

如何在MKAnnotationView图像上注册点击手势?

MKAnnotationView 和点击检测

IOS:将图像添加到自定义 MKAnnotationview

Swift - MKAnnotationView 地图引脚的自定义 UIView

如何使用 XIB 制作自定义 MKAnnotationView