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

时间:2022-09-06 20:47:06

Anyone know if there's a way to get click event from a button that is added to MKAnnotationView, this button is used as label just to display the name of each pin on the map , now I successd to show a custom view (which contains image, text ....) when the pin is clicked so i need to do the same thing when the button (label) is clicked.

任何人都知道是否有办法从添加到MKAnnotationView的按钮获取点击事件,此按钮用作标签只是为了显示地图上每个图钉的名称,现在我成功显示了一个自定义视图(包含图像,文本....)当单击该引脚时,我需要在单击按钮(标签)时执行相同的操作。

Thanks for any advice you can provide.

感谢您提供的任何建议。

code for button in MKAnnotationView:

MKAnnotationView中按钮的代码:

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];

3 个解决方案

#1


16  

The standard UI approach is to use the callout view and add an accessory button as progrmr shows.

标准UI方法是使用callout视图并在progrmr显示时添加附件按钮。

However, if you must add a button directly to the MKAnnotationView, the problems with your approach are that the MKPinAnnotationView's default frame (which can't easily be changed) is smaller than the button you're adding so most of the button will not respond to touches and even if you switch to using an MKAnnotationView and increase the frame size, the MKMapView will prevent the button from getting any touches.

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

What you'll need to do is add a UITapGestureRecognizer to the button (use the gesture handler's action method instead of an addTarget on the button) and add the button to a plain MKAnnotationView with an appropriate frame size instead of an MKPinAnnotationView.

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

Example:

例:

- (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);
}


Note that this will prevent the map view's didSelectAnnotationView delegate method from firing. If you need that method to fire (in addition to the button's gesture handler method), then add the following:

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

//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;
}

#2


3  

I added a button to the callout view (in my app) using this code (reduced for clarity):

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

-(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;
}

After doing this you need to implement the MKMapViewDelegate to handle callback to the delegate when the button is tapped:

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

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

#3


-1  

try passing the touches to the subview:

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

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

I'm surprised you have a problem though if your buttonView is in front? try making sure it is: [self bringSubviewToFront:pinButton];

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

#1


16  

The standard UI approach is to use the callout view and add an accessory button as progrmr shows.

标准UI方法是使用callout视图并在progrmr显示时添加附件按钮。

However, if you must add a button directly to the MKAnnotationView, the problems with your approach are that the MKPinAnnotationView's default frame (which can't easily be changed) is smaller than the button you're adding so most of the button will not respond to touches and even if you switch to using an MKAnnotationView and increase the frame size, the MKMapView will prevent the button from getting any touches.

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

What you'll need to do is add a UITapGestureRecognizer to the button (use the gesture handler's action method instead of an addTarget on the button) and add the button to a plain MKAnnotationView with an appropriate frame size instead of an MKPinAnnotationView.

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

Example:

例:

- (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);
}


Note that this will prevent the map view's didSelectAnnotationView delegate method from firing. If you need that method to fire (in addition to the button's gesture handler method), then add the following:

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

//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;
}

#2


3  

I added a button to the callout view (in my app) using this code (reduced for clarity):

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

-(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;
}

After doing this you need to implement the MKMapViewDelegate to handle callback to the delegate when the button is tapped:

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

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

#3


-1  

try passing the touches to the subview:

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

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

I'm surprised you have a problem though if your buttonView is in front? try making sure it is: [self bringSubviewToFront:pinButton];

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