【iOS】MKMapView の Custom CalloutView

こんにちは〜
見習いプログラマーのnaoponです!

みなさんは、iOSアプリで地図を使うとき何のマップを使っていますか? 僕はだいたい下記を使っています。

・Google の「GMSMapView」
・iOS の「MKMapView」

そして今回の『テーマ』はこちら↓↓↓
「iOSのコールアウトをカスタムしよう!」

目的は、
「Googleマップの吹き出し「infoWindow」と同じに、iOSマップの吹き出しも 好きなUIのコールアウトを出して使いたい」

■ カスタム手順の概要
1, InfoWindow作成
2, MKAnnotationのカスタム
3, MKPinAnnotationViewのカスタム
4, MKMapViewのカスタム
5, 実際に使ってみる

「んじゃ、どうやるの?」って話になりますよね。。

長々になってしまうので、簡潔に説明しますww
詳細は、ダウンロードしたサンプルを見てくださいね(^ ^;)

1, InfoWindowを作る

これは、各々UIViewをいつも通り作ってください。
サンプルでは、UIViewControllerベースにしてます。

2, MKAnnotationでアノテーションを作る

これも、各々いままで通りの作り方ですね。
好きなプロパティを定義して、色や画像や何やら好きにしちゃってください。

 


3, MKPinAnnotationViewでコールアウトを作る

※ここは重要かも
「AnnotationView」(ピン)は、タップされると、内部で「CalloutView」(吹き出し)を自身に addSubView します。

1: ピンをタップ
2: ピンの中で [ -(void)didAddSubview:(UIView *)subview{} ] が呼ばれる
3: ピンの中で [ -(void)layoutSubviews{} ] が呼ばれる

だから、やることとして、
1: CalloutViewの参照を確保
2: CalloutView上の標準UIをクリア
3: CalloutView上にオリジナルUIをaddSubView

[注意点]
A: CalloutViewのclipsToBoundsをNOにすること
B: layoutSubviewsは何回も呼ばれるので気をつけること

これで、カスタム吹き出しはOKです。

下記のtmpCalloutViewにCalloutViewの参照を格納します。
あとで使うのでViewのFrameを返すメソッドも1つ定義しておいてください。

 

※iOS7.0より前のバージョンでは「UICalloutView」、iOS7.0以上では「UIView」がコールアウトのViewとなります。

ちなみに「UICalloutView」をいじってリジェクトされないの?と不安になるかと思いますが、削除しているだけなので、リジェクトはされません。過去4度のApple申請でも、問題なくリリースすることができました!(ワ~イ)

上記コードの「ここ超重要☆」があるかと思いますが、なぜかというと、iOS7.0より前とiOS7.0以上では、コールアウトViewが持っているFrameサイズが極端に違います。

iOS7.0より前は、必要最低限のサイズで、iOS7.0以上は画面サイズがコールアウトViewの領域となり、オリジナルViewを追加した際に、領域からはみ出たレイアウトの部分が、カットされないようにします。self.tmpCalloutView.backgroundColorに好きな色をつけてみれば、地図上でコールアウトViewの領域がわかるかと思います。

次に、didAddSubviewのあとに、[-(void)layoutSubviews{}]が呼ばれます。

コールアウトのフレームサイズを返すメソッドも追加!


4, ちょっとだけマップをカスタム

マップのタッチイベントを拾えるようにします。
そして、吹き出しをタップされた場合に、マップのデリゲートメソッドでコールアウトがタップされたことをViewControllerに流しています。


5, 使ってみる

ふぅ〜〜〜
これでコールアウトのカスタムと実際に使うところまでが終了ですね。
以上『目標達成』ということで!

今は『コールアウトのタップイベント』をとっていますが、InfoWindowの中の各UIのFrameも判定に加えれば、『コールアウト内のどの項目がタップされたのか』もわかるかと思います。(Googleの方ができないのでiOSでそこまでは求めないかw)

サンプルはここからダウンロードできます。

みなさん参考になりましたか?
以上、見習いプログラマーnaoponでした〜!!