MKMapView MKPointAnnotation tap event

前端 未结 3 506
旧巷少年郎
旧巷少年郎 2020-11-29 20:17

I have a list of annotations (MKPointAnnotation). I have a UIViewController which is for the whole view, MKMapView implementing Controller, which I thought is useful for det

相关标签:
3条回答
  • 2020-11-29 21:09

    There are two ways of detecting user interaction with your annotation view. The common technique is to define a callout (that standard little popover bubble that you see when you tap on a pin in a typical maps app) for your MKAnnotationView. And you create the annotation view for your annotation in the standard viewForAnnotation method:

    - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
    {
        if ([annotation isKindOfClass:[MKUserLocation class]])
            return nil;
    
        MKAnnotationView *annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"loc"];
        annotationView.canShowCallout = YES;
        annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
    
        return annotationView;
    }
    

    By doing this, you get a callout, but you're adding an right accessory, which is, in my example above, a disclosure indicator. That way, they tap on your annotation view (in my example above, a pin on the map), they see the callout, and when they tap on that callout's right accessory (the little disclosure indicator in this example), your calloutAccessoryControlTapped is called (in my example below, performing a segue to some detail view controller):

    - (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
    {
        [self performSegueWithIdentifier:@"DetailsIphone" sender:view];
    }
    

    That's a very typical user experience on the small iPhone screen.

    But, if you don't like that UX and you don't want the standard callout, but rather you want something else to happen, you can define your MKAnnotationView so that a callout is not shown, but instead you intercept it and do something else (for example, on iPad maps apps, you might show some more sophisticated popover rather than the standard callout). For example, you could have your MKAnnotationView not show a callout:

    - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
    {
        if ([annotation isKindOfClass:[MKUserLocation class]])
            return nil;
    
        MKAnnotationView *annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"loc"];
        annotationView.canShowCallout = NO;
    
        return annotationView;
    }
    

    But you can then manually handle didSelectAnnotationView to detect when a user tapped on your MKAnnotationView, in this example showing a popover:

    - (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
    {
        [mapView deselectAnnotation:view.annotation animated:YES];
    
        DetailsViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:@"DetailsPopover"];
        controller.annotation = view.annotation;
        self.popover = [[UIPopoverController alloc] initWithContentViewController:controller];
        self.popover.delegate = self;
        [self.popover presentPopoverFromRect:view.frame
                                      inView:view.superview
                    permittedArrowDirections:UIPopoverArrowDirectionAny
                                    animated:YES];
    }
    

    I include some screen snapshots for the user interface yielded by the above code in my answer here.

    0 讨论(0)
  • 2020-11-29 21:09

    Add button in this method

    -(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation 
    {
      pinView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
      pinView.canShowCallout = YES;
    }
    
    Then callout method
    - (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
    {
          InfoView *infoView = [[InfoView alloc]initWithNibName:@"InfoView" bundle:nil];
            [self.navigationController pushViewController:infoView animated:YES];
    
    } 
    
    0 讨论(0)
  • 2020-11-29 21:13

    Robs example for Swift 3:

    class MapViewController: UIViewController
    {
        override func viewDidLoad()
        {
            super.viewDidLoad()
    
            // Create map view in storyboard
            view.delegate = self
        }
    }
    
    extension MapViewController: MKMapViewDelegate
    {
        func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView?
        {
            let annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "annotationView")
            annotationView.canShowCallout = true
            annotationView.rightCalloutAccessoryView = UIButton.init(type: UIButtonType.detailDisclosure)
    
            return annotationView
        }
    
        func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl)
        {
            guard let annotation = view.annotation else
            {
                return
            }
    
            let urlString = "http://maps.apple.com/?sll=\(annotation.coordinate.latitude),\(annotation.coordinate.longitude)"
            guard let url = URL(string: urlString) else
            {
                return
            }
    
            UIApplication.shared.openURL(url)
        }
    }
    
    0 讨论(0)
提交回复
热议问题