【Swift】detailCalloutAccessoryViewの使い方。ピンの吹き出しをカスタマイズする。(Swift 2.1、XCode 7.2)

2020年6月16日

吹き出しのカスタマイズ

過去の記事でさりげなく使っていたが、ピンのタイトルの左右に部品(以下、吹き出しアクセサリー)を追加することができる。

吹き出しに右ボタンを追加

 

タイトルの横に表示され、吹き出しのサイズを変更できない部品ため、デザインの自由度が今ひとつだった。そのため、地図に図形を描画して自作吹き出しを行う強者もいたようだ。

そんな中、iOS9でdetailCalloutAccessoryViewプロパティ(以下、詳細吹き出しアクセサリー)が登場し、吹き出しのサイズやレイアウトを簡単にカスタマイズできるようになった。

そこで本記事では、左右の吹き出しアクセサリーと、iOS9で登場した詳細吹き出しアクセサリーの使い方を説明する。

以降の手順は「Map Kit Viewの使い方」の続きから行うので、実装を試してみる人は先に読んでおくことをお勧めする。

 

左右の吹き出しアクセサリーを実装する

地図を長押しした座標にピンを刺し、吹き出しのタイトルの左右にボタンを表示する。左のボタンを押すとピンの色が変わり、右のボタンを押すとピンを削除するものを作ってみよう。

ピンの吹き出しに左右のボタンを追加する。

 

デバイス画面にLong Press Gesture Recognizerを配置する(下図赤矢印)。紫枠のアシスタントエディタボタンを押してViewController.swiftを開く。Ctrlキーを押しながら黄緑枠のジェスチャーリコグナイザーをドラッグ&ドロップでソースコードまで運んで吹き出しの設定画面を表示させる。

Connectionに「Action」、Nameに「pressMap」、Typeに「UILongPressGestureRecognizer」を設定しConnectボタンを押す。これで地図を長押ししたときのイベントをソースコードで受けれるようになった。

Long Press Gesture Recognizerをデバイス画面に配置する

 

UIViewController.swiftを以下のコードに変更する。

デリゲートメソッドの「アノテーションビューを返すメソッド」で左右の吹き出しアクセサリーをピンに追加している。

もう1つのデリゲートメソッド「吹き出しアクセサリー押下時の呼び出しメソッド」は左右どちらのボタンが押されても呼び出されるので、引数で渡ってきたcontrolと左の吹き出しアクセサリーが一致するかどうかで動作を場合分けしている。

 

以下は実際のプレイ動画。

 

ちなみにボタンのサイズを100×100ピクセルにした場合は下図のようになる。ボタンが大きくなっても吹き出しの高さは大きくならない。

ボタンのサイズを大きくしたときのピンの吹き出し

詳細吹き出しアクセサリーを実装する。

次にiOS9で登場した詳細吹き出しアクセサリーを試してみよう。

下図のように、店舗情報と詳細ボタンを縦に並べる吹き出しを実装する。部品を縦に並べるためにVirtical Stack View(以下、垂直スタックビュー)を利用する。⇒「Virtical Stack Viewとは

ピンを刺した場所に店、サービスがあるかはGoogle Places APIのプレイス検索で確認する。
detailCalloutAccessoryを使った作成イメージ

 

以降の手順は上記の手順の続きになるが、その前に公式ガイドの手順に従ってGoogle Places APIを利用するための準備をする必要がある。⇒「公式ガイド

準備でハマリやすそうな点は次の記事にまとめてあるので参照されたし。⇒「ハマりやすそうな点

準備が終わったらUIViewController.swiftを以下のコードに変更する。

ピンを刺す座標の半径5m以内に店やサービスがあるかをGoogle Places APIのプレイス検索で確認し、ある場合はプレイス詳細とプレイスフォトで店舗の詳細情報と写真を取得し、垂直スタックビューに追加している。

写真の取得に時間がかかるので、詳細吹き出しアクセサリーの設定が終わり次第ピンの色を青に変更して読み込み完了を知らせるようにした。半径5m以内に店、サービスが無い場合はピンは赤のままである。

「詳細を見る」ボタンを押したときの処理は実装していない。ちなみに、詳細吹き出しアクセサリーを使うとピンのサブタイトルは表示されなくなる。

 

以下は実際のプレイ動画。写真の読み込み完了までが遅いため、ピンが青くなるまでに時間がかかるのが気になるが、店の写真を吹き出しに大きく表示できるようになったのは嬉しい。