Reputation: 153
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.
Thanks for any advice you can provide.
code for button
in 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];
Upvotes: 14
Views: 15950
Reputation: 5393
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];
Upvotes: -1
Reputation:
The standard UI approach is to use the callout view and add an accessory button as progrmr shows.
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.
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
.
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:
//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;
}
Upvotes: 16
Reputation: 77173
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:
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
Upvotes: 3