Подтвердить что ты не робот

Разрешить постукивание в любом месте на выноске аннотации без вида аксессуара выноски

У меня есть вид карты, который добавляет аннотации более или менее следующим образом:

- (MKAnnotationView *)mapView:(MKMapView *)mapView
            viewForAnnotation:(id <MKAnnotation>) annotation
{
    MKAnnotationView *annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation
                                                                       reuseIdentifier:@"MKPinAnnotationView"];
    annotationView.canShowCallout = YES;

    UIButton *detailButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
    [detailButton addTarget:self
                     action:@selector(handleButtonAction)
           forControlEvents:UIControlEventTouchUpInside];
    annotationView.rightCalloutAccessoryView = detailButton;

    return annotationView;
}

В iOS 7 это помещает значок "i" в правую часть выноски. Нажатие на иконку запускает mapView:annotationView:calloutAccessoryControlTapped: (на делегате) и handleButtonAction: (для себя). Однако я недавно понял, что вы также можете нажать в другом месте на выноске, и будут запущены те же самые два метода.

Это происходит с помощью кнопки типа UIButtonTypeDetailDisclosure, но, похоже, она не работает с кнопкой UIButtonTypeCustom. Метод делегата также не запускается, когда я нажимаю на выноску, когда нет аксессуаров вообще. (Это поведение, конечно, не удивительно: удивительно, что если вспомогательный вид является кнопкой раскрытия подробностей, эти два метода запускаются независимо от того, нажимаете ли вы на кнопку непосредственно или где-то еще в выноске.)

Id нравится избавляться от кнопки в выноске или, по крайней мере, заменять ее кнопкой, отображающей мое собственное изображение вместо значка "i" на складе, в то же время позволяя пользователю нажимать в любом месте выноски для запуска моего действие. Это возможно? Я не вижу метод MKMapViewDelegate, который соответствует "выносу".

4b9b3361

Ответ 1

Попробуйте установить настраиваемое изображение для кнопки без изменения типа UIButtonTypeDetailDisclosure.

UIButton *detailButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];        
[detailButton setImage:[UIImage imageNamed:@"icon"] forState:UIControlStateNormal];

Для iOS7 и выше это изображение по умолчанию будет тонировано. Если вы хотите сохранить оригинальный значок, используйте следующие

[[UIImage imageNamed:@"icon"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]

Или если вы хотите удалить значок вообще

[detailButton setImage:[UIImage new] forState:UIControlStateNormal];

Ответ 2

Чтобы нажать кнопку выноски после того, как пользователь нажал на представление аннотации, добавьте UITapGestureRecognizer в didSelectAnnotationView. Таким образом, вы можете применить кран на выноске без необходимости просмотра аксессуаров.

Затем вы можете вернуть объект аннотации обратно от отправителя для дальнейшего действия.

- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
{
    UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self  action:@selector(calloutTapped:)];
    [view addGestureRecognizer:tapGesture];
}

-(void)calloutTapped:(UITapGestureRecognizer *) sender
{
    NSLog(@"Callout was tapped");

    MKAnnotationView *view = (MKAnnotationView*)sender.view;
    id <MKAnnotation> annotation = [view annotation];
    if ([annotation isKindOfClass:[MKPointAnnotation class]])
    {
        [self performSegueWithIdentifier:@"annotationDetailSegue" sender:annotation];
    }
}

Ответ 3

Dhanu Решение в Swift 3:

func mapView(mapView: MKMapView, didSelectAnnotationView view:MKAnnotationView) {
    let tapGesture = UITapGestureRecognizer(target:self,  action:#selector(calloutTapped(sender:)))
    view.addGestureRecognizer(tapGesture)
}

func mapView(mapView: MKMapView, didDeselectAnnotationView view: MKAnnotationView) {
    view.removeGestureRecognizer(view.gestureRecognizers!.first!)
}

func calloutTapped(sender:UITapGestureRecognizer) {
    let view = sender.view as! MKAnnotationView
    if let annotation = view.annotation as? MKPointAnnotation {
        performSegue(withIdentifier: "annotationDetailSegue", sender: annotation)
    }
}

Ответ 4

Если вам не нужна индикация крана, я бы посоветовал выбросить UITapGestureRecognizer в выноску при создании и добавить ваш объект обработки (возможно, контроллер) в качестве цели с соответствующим действием.

Ответ 5

- (void)mapView:(MKMapView *)mv annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
    Park *parkAnnotation = (Park *)[view annotation];
    switch ([control tag]) {
        case 0: // left button
        {
            NSURL *url = [NSURL URLWithString:parkAnnotation.link];
            [[UIApplication sharedApplication] openURL:url];
        }
            break;

        case 1: // right button
        {
            // build a maps url. This will launch the Maps app on the hardware, and the apple maps website in the simulator
            CLLocationCoordinate2D coordinate = self.locationManager.location.coordinate;
            NSString *url2 = [NSString stringWithFormat:@"http://maps.apple.com/maps?saddr=%f,%f&daddr=%f,%f",coordinate.latitude,coordinate.longitude,parkAnnotation.location.coordinate.latitude,parkAnnotation.location.coordinate.longitude];

            [[UIApplication sharedApplication] openURL:[NSURL URLWithString:url2]];
        }
            break;

        default:
            NSLog(@"Should not be here in calloutAccessoryControlTapped, tag=%ld!",(long)[control tag]);
            break;
    }
}