Разрешить постукивание в любом месте на выноске аннотации без вида аксессуара выноски
У меня есть вид карты, который добавляет аннотации более или менее следующим образом:
- (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
, который соответствует "выносу".
Ответы
Ответ 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;
}
}