Xamarin逆引きTips
Xamarin.iOSで地図にマーカーを表示するには?(MapKit使用)
Xamarin.iOSでiOS標準の地図ライブラリ「MapKit」を使って、マーカーを追加/削除するには? また、マーカー選択時の処理や、吹き出し表示、吹き出しタップ時の処理の、基本的な実装方法を説明する。
前回に引き続き、Xamarin.iOSでMapKitを使用する。今回はマーカーや吹き出しを表示する方法を解説する。
「Tips:Xamarin.iOSで地図に図形を表示するには?(MapKit使用)」の続きとして解説するので、プロジェクトの準備は前回を参照してほしい。
1. 画面を準備する
 前回終了時点で、MainStoryboard.storyboardファイルを開くと、以下の画面のようになっているはずだ。
 これに「マーカーを追加」「マーカーを削除」するためのボタンをそれぞれ追加する(図2)。[Name]は、それぞれbuttonAddMarker、buttonDeleteMarkerとする。また、それぞれの[Title]プロパティを指定して、[Add Marker]ボタン、[Delete Marker]ボタンとする。
2. マーカーを追加する
 マーカーの描画は、MKMapViewDelegateプロトコルを実装したクラスを経由して行われる。そのため、以下のような、MKMapViewDelegateを継承したクラスMyMapViewDelegateを作成して実装する。
| 
 using MonoTouch.Foundation; 
using MonoTouch.MapKit; 
public class MyMapViewDelegate : MKMapViewDelegate 
{ 
  const string PIN_ID = "myPin"; 
  public override MKAnnotationView GetViewForAnnotation( 
    MKMapView mapView, NSObject annotation) //<--3 
  { 
    var pinView = mapView.DequeueReusableAnnotation(PIN_ID) as MKPinAnnotationView; //<--4 
    if (pinView == null) 
    { 
      pinView = new MKPinAnnotationView(annotation, PIN_ID); 
    }  
    pinView.PinColor = MKPinAnnotationColor.Red; 
    return pinView; //<--5 
  } 
} 
 | 
 次に、MapKitSampleViewController.csファイルに、[Add Marker]ボタンを押した時にマーカーを追加するコードを、以下のように記述する。
| 
 public partial class MapKitSampleViewController : UIViewController 
{ 
  ……省略…… 
  public override void ViewDidLoad() 
  { 
    base.ViewDidLoad(); 
    ……省略…… 
    mapView.Delegate = new MyMapViewDelegate(); //<--1 
    MKPointAnnotation annotation = null; 
    buttonAddMarker.TouchUpInside += (sender, e) =>  
    { 
      if (annotation != null)  
      { 
        return; 
      } 
      annotation = new MKPointAnnotation() //<--2 
      { 
        Title = "東京スカイツリー", 
        Coordinate = new CLLocationCoordinate2D(35.710063, 139.8107) 
      }; 
      mapView.AddAnnotation(annotation); 
    }; 
  } 
} 
 | 
 1で、先に作成したMyMapViewDelegateクラスのインスタンスを生成してMapViewに設定する。
 次に2で、ボタンを押した時に、MKPointAnnotationオブジェクトを生成して、MKMapViewに追加(=AddAnnotationメソッド)している。ここでは東京スカイツリーの位置を示している。
 次に、描画のためにマーカーが必要になると、3のGetViewForAnnotationメソッドが呼び出される。4で、PIN_IDを指定してDequeueReusableAnnotationメソッドを呼び出しているが、これはマーカーを都度生成せず、使い回すための仕組みだ。この返値は、初回は当然nullなので、new MKPinAnnotationView(...)によりマーカーのためのViewを生成し、色を赤に設定して返却する(5)。
3. マーカーを削除する
次に、追加したマーカーを削除する方法を解説する。
 MapKitSampleViewController.csファイルに、[Delete Marker]ボタンを押した時にマーカーを削除するコードを、以下のように記述する。
| 
 public partial class MapKitSampleViewController : UIViewController 
{ 
  ……省略…… 
  public override void ViewDidLoad() 
  { 
    base.ViewDidLoad(); 
    ……省略…… 
    mapView.Delegate = new MyMapViewDelegate(); 
    MKPointAnnotation annotation = null; 
    ……省略…… 
    buttonDeleteMarker.TouchUpInside += (sender, e) =>  
    { 
      if (annotation == null)  
      { 
        return; 
      } 
      mapView.RemoveAnnotation(annotation); //<--1 
      annotation = null; 
    }; 
  } 
} 
 | 
 マーカーの削除は1で、MapViewオブジェクトのRemoveAnnotationメソッドを呼び出すだけだ。また、削除済みのannotationを渡してしまわないよう、事前にチェックしている。
ここまでのプログラムを実行すると、図3のようになる。

[Add Marker]ボタンを押すと、東京スカイツリーの位置に赤色のマーカーが表示される。
[Delete Marker]ボタンを押すと、マーカーが削除される。
4. マーカーが選択された時に処理を行う
続いて、マーカーをタップして選択した時に何らかの処理を行う方法を解説する。
 MyMapViewDelegate.csファイルに以下のようにコードを追加する。
| 
 using System; 
using MonoTouch.UIKit; 
public class MyMapViewDelegate : MKMapViewDelegate 
{ 
  ……省略…… 
  public override void DidSelectAnnotationView(MKMapView mapView,  
    MKAnnotationView view) //<--1 
  { 
    var alertView = new UIAlertView(String.Empty, "マーカーが選択されました",  
      null, "閉じる", null); 
    alertView.Clicked += (sender, e) =>  
    { 
      mapView.DeselectAnnotation(view.Annotation, false); //<--2 
    }; 
    alertView.Show(); 
  } 
} 
 | 
 マーカーを選択すると、DidSelectAnnotationViewメソッドが呼び出されるので、このメソッドをオーバーライドする(1)。
 なお、Xamarin Studioのコード補完機能により、このメソッドを追加すると、以下のようなコメントが表示される。これが示す通り、base.DidSelectAnnotationView()を呼び出してはいけないことに注意してほしい。
| 
 // NOTE: Don't call the base implementation on a Model class 
// see http://docs.xamarin.com/guides/ios/application_fundamentals/delegates,_protocols,_and_events 
 | 
 上記のDidSelectAnnotationViewメソッドの実装では、UIAlertView(=アラート)を表示している。ダイアログを閉じた時に、MapViewオブジェクトのDeselectAnnotationメソッドを呼び出して「選択を解除」することを忘れないでほしい(2)。選択状態のままだと、2回目のタップ時に、このメソッドは呼び出されない。
ここまでのプログラムを実行すると、図4のようになる。

マーカーを選択すると、「マーカーが選択されました」と表示される。
5. 吹き出しを表示し、吹き出しが押された時に処理を行う
最後に、マーカーの上に吹き出しを表示する方法、およびその吹き出しがタップされた時に処理を行う方法について解説する。
 MyMapViewDelegate.csファイルのコードを、以下のように変更する。
| 
 public class MyMapViewDelegate : MKMapViewDelegate 
{ 
  const string PIN_ID = "myPin"; 
  public override MKAnnotationView GetViewForAnnotation( 
    MKMapView mapView, NSObject annotation) 
  { 
    var pinView = mapView.DequeueReusableAnnotation(PIN_ID) as MKPinAnnotationView; 
    if (pinView == null) 
    { 
      pinView = new MKPinAnnotationView(annotation, PIN_ID); 
    }  
    pinView.PinColor = MKPinAnnotationColor.Red; 
    // 1 追記 ここから ———— 
    pinView.CanShowCallout = true; 
    pinView.RightCalloutAccessoryView = UIButton.FromType(UIButtonType.DetailDisclosure); 
    // ———— ここまで 
    return pinView; 
  } 
  // 2 追記 ここから ———— 
  public override void CalloutAccessoryControlTapped( 
    MKMapView mapView, MKAnnotationView view, UIControl control) 
  { 
    new UIAlertView(String.Empty, "吹き出しがタップされました",  
      null, "閉じる", null).Show(); 
  } 
  // ———— ここまで 
  public override void DidSelectAnnotationView(MKMapView mapView, MKAnnotationView view) 
  { 
// 3 マーカー選択処理をコメントアウト 
//    var alertView = new UIAlertView(String.Empty, "マーカーが選択されました",  
//      null, "閉じる", null); 
// 
//    alertView.Clicked += (sender, e) =>  
//    { 
//      mapView.DeselectAnnotation(view.Annotation, false); 
//    }; 
// 
//    alertView.Show(); 
  } 
} 
 | 
 1で、MKPinAnnotationViewオブジェクトのCanShowCalloutプロパティをtrueにすることで、マーカーをタップした時に、その上に吹き出しが表示されるようになる。吹き出しに表示されるのは、MKPointAnnotationオブジェクトのTitleプロパティ値の文字列だ。
 pinView.RightCalloutAccessoryViewの行は、吹き出しの右端に表示するボタンの設定だ。
 2が、吹き出しをタップした時に呼び出されるメソッドだ。ここでは「吹き出しがタップされました」というUIAlertViewを表示している。
 吹き出しのタップでは通常、マーカーを選択解除する必要はないので、DeselectAnnotationメソッドを呼び出す必要はない。そこで3で、先ほど追加したマーカーの選択時の処理をコメントアウトしている。
 吹き出しを選択するために、マーカーの選択をする必要があるが、その際にアラートを表示するのはふさわしくないだろう。ちなみにDidSelectAnnotationViewメソッド自体は吹き出しがあっても呼び出されるので、何らかの処理を行うことは可能だ。
ここまでのプログラムを実行すると、図5のようになる。
マーカーを選択すると吹き出しが表示され、吹き出しをタップすると「吹き出しがタップされました」と表示される。
まとめ
前々回、前回、そして今回で、Xamarin.iOSでのMapKitの基本的な使用方法を解説した。
今回のマーカーの使用については、Xamarin Developer Center(英語)の、
を、Xamarin.iOSでのMapKit利用の全体については、同じくXamarin Developer Center(英語)の、
を参照されたい。
次回以降では、Xamarin.AndroidでGoogleマップを表示する方法を解説する予定だ。
※以下では、本稿の前後を合わせて5回分(第17回~第21回)のみ表示しています。
 連載の全タイトルを参照するには、[この記事の連載 INDEX]を参照してください。
17. Xamarin.iOSで地図を表示するには?(MapKit使用)
Xamarin.iOSでiOS標準の地図ライブラリ「MapKit」を使って地図を表示する方法を解説。また、地図の種類の変更、ジェスチャの有効/無効の切り替えなども説明する。
18. Xamarin.iOSで地図に図形を表示するには?(MapKit使用)
Xamarin.iOSでiOS標準の地図ライブラリ「MapKit」を使って、ライン、ポリゴン、円などの図形を地図上に表示する方法を解説する。
19. 【現在、表示中】≫ Xamarin.iOSで地図にマーカーを表示するには?(MapKit使用)
Xamarin.iOSでiOS標準の地図ライブラリ「MapKit」を使って、マーカーを追加/削除するには? また、マーカー選択時の処理や、吹き出し表示、吹き出しタップ時の処理の、基本的な実装方法を説明する。
20. Xamarin.Androidで地図を表示するには?(Google Maps使用)
Androidで最も一般的な地図API「Google Maps Android API v2」を使って、Xamarin.Androidで地図を表示する方法を解説。API利用環境の準備から、まずはGoogleマップを表示するまでの手順を説明する。
21. Xamarin.Androidで地図を操作するには?(Google Maps使用)
「Google Maps Android API v2」を使って、Xamarin.Androidアプリで地図の表示位置や種類を変更する方法、ジェスチャの有効/無効を切り替える方法などを説明する。