user2652032
user2652032

Reputation: 85

Callout Annotation view is not clickable the center

I want all my view is tappable and not just leftCalloutAccessoryView or rightCalloutAccessoryView, I also want the center to be tappable as well

enter image description here

Upvotes: 1

Views: 1254

Answers (2)

abbood
abbood

Reputation: 23558

the idea is that you want to make all of the "accessory view" tappable without interfering with the original tap of the actual annotation.. this is how i do it:

first I create and assign a tap gesture to the annotation view after it has been selected like so (I use obj-c runtime object association here.. see this gist):

// set up vars
static NSString *const kExtraTapGestureRecognizer = @"extraGesture";
UIControl *currentAnnotationControl;

- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view {      
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]
                                   initWithTarget:self 
                                           action:@selector(handleAnnotationViewTap:)];
    tap.numberOfTapsRequired = 1;
    [tap setInfo:kExtraTapGestureRecognizer];
    [view addGestureRecognizer:tap];

}

to handle the tap, I call MKMapViewDelegate Protocol's mapView:annotationView:calloutAccessoryControlTapped:, which basically means that if the view in between the accessory views gets tapped, it's as if one of the accessory views just got tapped:

- (void)handleAnnotationViewTap:(UITapGestureRecognizer *)gestureRecognizer {
    MKAnnotationView *annotationView = (MKAnnotationView *)gestureRecognizer.view;
    // currentAnnotationControl is just a reference to one of the 
    // accessory views of the annotation that has just been selected.. 
    // see comment below
    [self mapView:self.mapView 
   annotationView:annotationView 
   calloutAccessoryControlTapped:currentAnnotationControl];
}

when the annotationView is returned, I save a reference to one of its (left or right) accessoryViews like so:

- (MKAnnotationView *)mapView:(MKMapView *)theMapView viewForAnnotation:(id <MKAnnotation>)annotation
{
    if ([annotation isKindOfClass:[Random class]])
    {
        static NSString *annotationIdentifier = @"annotation";

        MKAnnotationView *annotationView =
        (MKAnnotationView *) [self.mapView annotationIdentifier];
        if (annotationView == nil)
        {
            annotationView = [[MKAnnotationView alloc]
                               initWithAnnotation:annotation reuseIdentifier:RiderAnnotationIdentifier];
            annotationView.canShowCallout = YES;

            UIButton *leftButton = [UIButton buttonWithType:UIButtonTypeCustom];
            leftButton.frame = CGRectMake(0, 0,21, 21);
            [leftButton setImage:[UIImage imageNamed:@"smallInfo_rider_left.png"] forState:UIControlStateNormal];

            [leftButton addTarget:nil action:nil forControlEvents:UIControlEventTouchUpInside];
            annotationView.leftCalloutAccessoryView = leftButton;

            // this is where i store a reference to one of the accessory views
            currentAnnotationControl = leftButton;

            return annotationView;
        }
        else
        {
            annotationView.annotation = annotation;
        }

        return annotationView;

keep in mind that we created an extra tap gesture, we must get rid of it as soon as one of the accessory views has been tapped like so:

- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
    // we remove the extra tap gesture so that it doesn't interfere
    // with normal app flow in the future
    for (UIGestureRecognizer *gesture in [view gestureRecognizers]) {
        if ([[gesture info] isEqualToString:kExtraTapGestureRecognizer]) {
            [gesture removeTarget:nil action:NULL];
        }            
    }
    // more stuff

Upvotes: 1

karthika
karthika

Reputation: 4091

You can use,

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [touches anyObject];

    CGPoint touchPoint = [touch locationInView:calloutView];

        BOOL isPointInsideView = [calloutView pointInside:touchPoint withEvent:nil];
        if (isPointInsideView)
        {
           // place your action code.  
        }

}

or you can use,

    UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapCalloutAction:)];
    tapGestureRecognizer.delegate = self;
    tapGestureRecognizer.numberOfTapsRequired = 1;
    [calloutView addGestureRecognizer:tapGestureRecognizer];

-(void) tapCalloutAction:(id)sender
{
    // do stuff
}

Upvotes: 2

Related Questions