praks5432
praks5432

Reputation: 7792

Button not working in custom callout

So I've tried this-

-(void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view{
    [self.mapAnnotationViewController.view removeFromSuperview];
    MyLocation* location = (MyLocation*)view.annotation;
    currentResultDictionary = [location cardJson];
    [self.mapAnnotationViewController setAnnotationTitle: [location title]];
    [self.mapAnnotationViewController setRating:3.0];
    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
    UIImage* forwardButtonImage = [UIImage imageNamed:@"forward-50x50.png"];
    button.frame = CGRectMake(141,5,25,25);
    [button setBackgroundImage:forwardButtonImage forState:UIControlStateNormal];
    [button addTarget:self action:@selector(displayCard:) forControlEvents:UIControlEventTouchUpInside];

    //Since we are re-using the callout view,
    //may need to do additional "cleanup" so that the callout
    //shows the new annotation's data.

    [view addSubview:self.mapAnnotationViewController.view];
    [view addSubview: button];
}

-(IBAction)displayCard:(id)sender{
    NSLog(@"DISPLAY CARD CALLED");
}

This adds the button successfully, but when I click on it, the displayCard method is not being called. Why is that happening?

So this is probably why it's not working -

How To add custom View in map's Annotation's Callout's

However, that solution subclasses the view - I only have access to the controller. Can I reduce my problem to be solved by that solution?

Upvotes: 3

Views: 1404

Answers (1)

user467105
user467105

Reputation:

Based on your previous question, the problem here is that the button's frame is outside the frame of the pin annotation view. Therefore, touches on the button do nothing.

Assuming you are still using the default MKPinAnnotationView, the default view size is about 32 x 32. Since the button is being added as a subview to it at an x coordinate of 141, it is outside the parent view's frame and touches don't work.

One solution (though it leads to other issues) is to modify the MKPinAnnotationView's frame so that the button will included. So in viewForAnnotation, after the view is created, you could put:

pav = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"pin"];
pav.canShowCallout = NO;
//increase the frame size to include the button...
pav.frame = CGRectMake(0, 0, 200, 40);
//adjust contentMode otherwise default pin image will be distorted...
pav.contentMode = UIViewContentModeTopLeft;

I don't recommend the above. This may work but may lead to other issues.


A better solution probably is to add your custom callout view not to the annotation view but to your main view controller's view. This way, you don't need to mess with the annotation view. You'll need to convert the selected pin's coordinate to the corresponding CGPoint in the main view and set the custom callout view's origin to that point. In didSelectAnnotationView:

[self.mapAnnotationViewController.view removeFromSuperview];

CGRect mavcFrame = mapAnnotationViewController.view.frame;
CGPoint p = [mapView convertCoordinate:view.annotation.coordinate toPointToView:self.view];
//You may need/want to adjust p after the conversion depending on where 
//you want the callout view to appear relative to the annotation.
mavcFrame.origin = p;
mapAnnotationViewController.view.frame = mavcFrame;

//add subview to self.view instead of view...
[self.view addSubview:self.mapAnnotationViewController.view];

Also, I don't recommend adding the button in the didSelectAnnotationView as you will end up with duplicate buttons that don't get removed every time an annotation is selected.

Instead, create and add the button once to the mapAnnotationViewController.view right after the mapAnnotationViewController is created.

Upvotes: 3

Related Questions