允许在没有标注附件视图的情况下点击注释标注上的任何位置

时间:2014-03-02 20:31:20

标签: ios mkmapview

我有一个地图视图,可以添加或多或少的注释:

- (MKAnnotationView *)mapView:(MKMapView *)mapView
            viewForAnnotation:(id <MKAnnotation>) annotation
{
    MKAnnotationView *annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation
                                                                       reuseIdentifier:@"MKPinAnnotationView"];
    annotationView.canShowCallout = YES;

    UIButton *detailButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
    [detailButton addTarget:self
                     action:@selector(handleButtonAction)
           forControlEvents:UIControlEventTouchUpInside];
    annotationView.rightCalloutAccessoryView = detailButton;

    return annotationView;
}

在iOS 7中,这会在标注的右侧放置一个“i”图标。点击图标会触发mapView:annotationView:calloutAccessoryControlTapped:(代表上)和handleButtonAction:(自我)。不过,我最近意识到你也可以点击标注上的其他任何地方,并且会触发相同的两种方法。

使用UIButtonTypeDetailDisclosure类型的按钮会发生这种情况,但UIButtonTypeCustom按钮似乎不会发生这种情况。当没有附件视图时点击标注时,也不会触发委托方法。 (当然,这种行为并不令人惊讶;令人惊讶的是,如果附件视图是详细信息泄露按钮,则无论您是点击按钮本身还是只是某处,都会触发这两种方法 其他在标注中。)

我想摆脱标注中的按钮 - 或者至少用显示我自己的图像而不是股票“i”图标的按钮替换它 - 同时仍然允许用户点击标注上的任何位置触发我的行动。这可能吗?我没有看到与“callout tapped”对应的MKMapViewDelegate方法。

5 个答案:

答案 0 :(得分:29)

尝试在不更改UIButtonTypeDetailDisclosure类型的情况下为按钮设置自定义图像。

UIButton *detailButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];        
[detailButton setImage:[UIImage imageNamed:@"icon"] forState:UIControlStateNormal];

对于iOS7及以上版本,此图像默认会着色。如果您想保留原始图标,请使用以下

[[UIImage imageNamed:@"icon"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]

或者,如果您想要删除图标

[detailButton setImage:[UIImage new] forState:UIControlStateNormal];

答案 1 :(得分:9)

要在用户点击“注释”视图后点按标注按钮,请在UITapGestureRecognizer中添加didSelectAnnotationView。通过这种方式,您可以在不需要附件视图的情况下实现对标注的点击。

然后,您可以从发件人处获取注释对象以进行进一步操作。

- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
{
    UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self  action:@selector(calloutTapped:)];
    [view addGestureRecognizer:tapGesture];
}

-(void)calloutTapped:(UITapGestureRecognizer *) sender
{
    NSLog(@"Callout was tapped");

    MKAnnotationView *view = (MKAnnotationView*)sender.view;
    id <MKAnnotation> annotation = [view annotation];
    if ([annotation isKindOfClass:[MKPointAnnotation class]])
    {
        [self performSegueWithIdentifier:@"annotationDetailSegue" sender:annotation];
    }
}

答案 2 :(得分:7)

Swift 3中的

Dhanu A's solution

func mapView(mapView: MKMapView, didSelectAnnotationView view:MKAnnotationView) {
    let tapGesture = UITapGestureRecognizer(target:self,  action:#selector(calloutTapped(sender:)))
    view.addGestureRecognizer(tapGesture)
}

func mapView(mapView: MKMapView, didDeselectAnnotationView view: MKAnnotationView) {
    view.removeGestureRecognizer(view.gestureRecognizers!.first!)
}

func calloutTapped(sender:UITapGestureRecognizer) {
    let view = sender.view as! MKAnnotationView
    if let annotation = view.annotation as? MKPointAnnotation {
        performSegue(withIdentifier: "annotationDetailSegue", sender: annotation)
    }
}

答案 3 :(得分:3)

如果您不需要点击指示,我建议您在创建时将UITapGestureRecognizer投入到标注中,并将您的处理对象(可能是控制器)添加为具有适当操作的目标。

答案 4 :(得分:0)

- (void)mapView:(MKMapView *)mv annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
    Park *parkAnnotation = (Park *)[view annotation];
    switch ([control tag]) {
        case 0: // left button
        {
            NSURL *url = [NSURL URLWithString:parkAnnotation.link];
            [[UIApplication sharedApplication] openURL:url];
        }
            break;

        case 1: // right button
        {
            // build a maps url. This will launch the Maps app on the hardware, and the apple maps website in the simulator
            CLLocationCoordinate2D coordinate = self.locationManager.location.coordinate;
            NSString *url2 = [NSString stringWithFormat:@"http://maps.apple.com/maps?saddr=%f,%f&daddr=%f,%f",coordinate.latitude,coordinate.longitude,parkAnnotation.location.coordinate.latitude,parkAnnotation.location.coordinate.longitude];

            [[UIApplication sharedApplication] openURL:[NSURL URLWithString:url2]];
        }
            break;

        default:
            NSLog(@"Should not be here in calloutAccessoryControlTapped, tag=%ld!",(long)[control tag]);
            break;
    }
}