Как получить событие нажатия кнопки, добавленной через MKAnnotationView - PullRequest
14 голосов
/ 04 августа 2011

Кто-нибудь знает, есть ли способ получить событие щелчка от button, который добавляется к MKAnnotationView, этот button используется в качестве метки только для отображения названия каждого вывода на map, теперь удалось показать пользовательский view (который содержит изображение, текст ....) при нажатии pin, поэтому мне нужно сделать то же самое при нажатии кнопки (метки).

Спасибо за любой совет, который вы можете дать.

код для button в 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];

Ответы [ 3 ]

16 голосов
/ 04 августа 2011

Стандартный подход пользовательского интерфейса заключается в использовании представления выноски и добавлении вспомогательной кнопки, как показывает progrmr.

Однако, если вам необходимо добавить кнопку непосредственно к MKAnnotationView, проблемы с вашим подходом заключаются в том, чторамка по умолчанию MKPinAnnotationView (которую нельзя легко изменить) меньше, чем кнопка, которую вы добавляете, поэтому большая часть кнопки не будет реагировать на прикосновения, даже если вы переключитесь на использование MKAnnotationView и увеличитеразмер кадра, MKMapView предотвратит прикосновения к кнопке.

Что вам нужно сделать, это добавить UITapGestureRecognizer к кнопке (используйте метод действия обработчика жестов вместо addTarget длякнопку) и добавьте кнопку к обычному MKAnnotationView с соответствующим размером кадра вместо MKPinAnnotationView.

Пример:

- (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);
}


Обратите внимание, что это предотвратит* делегат didSelectAnnotationView метода представления карты от стрельбы.Если вам нужен этот метод для запуска (в добавление к методу обработчика жестов кнопки), добавьте следующее:

//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;
}
3 голосов
/ 04 августа 2011

Я добавил кнопку в представление выноски (в моем приложении), используя этот код (уменьшен для ясности):

-(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;
}

После этого вам необходимо реализовать MKMapViewDelegate для обработки обратного вызова делегату, когдакнопка нажата:

- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
0 голосов
/ 04 августа 2011

попробуйте передать прикосновения к подпредставлению:

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
 [pinButton touchesEnded:touches withEvent:event];
}

Я удивлен, что у вас есть проблема, если ваш buttonView находится впереди? попробуйте убедиться, что это: [self takeSubviewToFront: pinButton];

...