私は多かれ少なかれ次のような注釈を追加するマップビューを持っています:
- (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:
(自分自身上)がトリガーされます。ただし、最近、コールアウトの他の場所をタップすることもでき、同じ2つのメソッドが実行されることに気付きました。
これは、タイプUIButtonTypeDetailDisclosure
のボタンで発生しますが、UIButtonTypeCustom
ボタンでは発生しないようです。アクセサリビューがまったくないときにコールアウトをタップしても、デリゲートメソッドは実行されません。 (もちろん、その動作は驚くべきことではありません。驚くべきことは、アクセサリビューが詳細開示ボタンの場合、これら2つのメソッドがに関係なく実行されることです。ボタン自体をタップするのか、吹き出しのどこかをタップするのか。)
コールアウトのボタンを削除するか、少なくとも、ユーザーがコールアウトの任意の場所をタップしてアクションをトリガーできるようにしながら、ストックの「i」アイコンの代わりに自分の画像を表示するボタンに置き換えたい。これは可能ですか? 「コールアウトタップ」に対応するMKMapViewDelegate
メソッドが表示されません。
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];
ユーザーが注釈ビューをクリックした後にコールアウトボタンをタップするには、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];
}
}
タップ表示が必要ない場合は、作成時にUITapGestureRecognizer
をコールアウトにスローし、適切なアクションでターゲットとして処理オブジェクト(おそらくコントローラー)を追加することをお勧めします。
- (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;
}
}