Xamarin逆引きTips

Xamarin逆引きTips

Xamarin.Androidで地図に図形を表示するには?(Google Maps使用)

2014年10月10日

「Google Maps Android API v2」を使って、Xamarin.Androidアプリで地図上にライン/ポリゴン/円などの図形を表示する方法を解説する。

奥山 裕紳(@amay077
  • このエントリーをはてなブックマークに追加

 前回に引き続き、Xamarin.AndroidアプリでGoogle Maps Android API v2(以下、「GoogleMapAPI」と表記)を使用する。今回はライン、ポリゴン、円などの図形を表示する方法を解説する。

 「Tips:Xamarin.Androidで地図を操作するには?(Google Maps使用)」の続きとして解説するので、プロジェクトの準備は前回を参照してほしい。

1. 画面を準備する

 前回終了時点で、Main.axmlファイルを開くと、以下のようになっているはずだ。

AXML
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent">
  <fragment
    android:id="@+id/map"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:name="com.google.android.gms.maps.MapFragment" />
  <Button
    android:id="@+id/buttonCenter"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentLeft="true"
    android:layout_alignParentBottom="true"
    android:text="Center" />
  <Button
    android:id="@+id/buttonBounds"
    android:layout_toRightOf="@+id/buttonCenter"
    android:layout_alignTop="@+id/buttonCenter"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Bounds" />
  <Button
    android:id="@+id/buttonCamera"
    android:layout_toRightOf="@+id/buttonBounds"
    android:layout_alignTop="@+id/buttonCenter"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Camera" />
</RelativeLayout>
前回終了時点のUIデザイン内容(Main.axml)

 これを、以下のように修正してボタンを追加する。

AXML
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
1
34
35
36
37
38
39
2
41
42
43
44
45
46
3
48
49
50
51
52
53
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent">
  <fragment
    android:id="@+id/map"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:name="com.google.android.gms.maps.MapFragment" />
  <Button
    android:id="@+id/buttonCenter"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentLeft="true"
    android:layout_alignParentBottom="true"
    android:text="Center" />
  <Button
    android:id="@+id/buttonBounds"
    android:layout_toRightOf="@+id/buttonCenter"
    android:layout_alignTop="@+id/buttonCenter"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Bounds" />
  <Button
    android:id="@+id/buttonCamera"
    android:layout_toRightOf="@+id/buttonBounds"
    android:layout_alignTop="@+id/buttonCenter"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Camera" />

  <Button
    android:id="@+id/buttonLine"
    android:layout_alignLeft="@+id/buttonCenter"
    android:layout_above="@+id/buttonCenter"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Line" />
  <Button
    android:id="@+id/buttonPolygon"
    android:layout_alignLeft="@+id/buttonBounds"
    android:layout_above="@+id/buttonBounds"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Polygon" />
  <Button
    android:id="@+id/buttonCircle"
    android:layout_alignLeft="@+id/buttonCamera"
    android:layout_above="@+id/buttonCamera"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Circle" />
</RelativeLayout>
今回のUIデザイン内容(Main.axml)

 これをUIデザイナーで確認すると、図1のようになる。

図1 ボタンを追加したMain.axml

 前回までの画面にある[Center][Bounds][Camera]ボタンの上に、13で、それぞれ[Line][Polygon][Circle]ボタンを配置している。

2. ラインを描画する

 MainActivity.csファイルに、[Line]ボタンを押した時にラインを追加するコードを、以下のように記述する。

C#
using Android.Graphics;
……省略……

[Activity(Label = "GoogleMapSample", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : Activity
{
  protected override void OnCreate(Bundle bundle)
  {
    base.OnCreate(bundle);

    ……省略……

    FindViewById<Button>(Resource.Id.buttonLine).Click += (sender, e) => 
    {
      map.AddPolyline(new PolylineOptions() //<--1
        .Add(new LatLng(35.531d, 139.697d)) // 川崎駅付近
        .Add(new LatLng(35.562d, 139.716d)) // 蒲田駅付近
        .Add(new LatLng(35.589d, 139.668d)) // 多摩川駅付近
        .InvokeColor(Color.Blue)
        .InvokeWidth(5f)
      );
    };
  }
}
[Line]ボタンを押した時に、ラインを追加するコード(MainActivity.cs)

 1で、[Line]ボタンを押した時に、map.AddPolylineメソッドを呼び出して、ラインを地図に追加している。引数はPolylineOptionオブジェクトで、このオブジェクトに対し、ラインに関するさまざまなパラメーターを設定する。Addは座標(緯度経度)の追加(緯度経度のリストを指定するAddAllメソッドもある)、InvokeColorで線の色を、InvokeWidthで線幅を指定する。

【コラム】InvokeColorメソッドとFillColorプロパティ

 ラインの色を設定するメソッドは、ネイティブのAPIではPolylineOption.colorメソッドであるが、このメソッドはメソッドチェーンで他のメソッドが呼び出せるように、自分自身を返却するメソッドになっている。一方、線幅を取得するためのPolylineOption.getColorメソッドも存在する。Xamarin.Androidでは、通常、Javaのgetter/setterメソッドはC#言語のプロパティに置き換えられるが、前述のようにcolorメソッドが単なるsetterではなく値を返却するメソッドなので、

  • colorメソッド(Java) → InvokeColorメソッド(C#)
  • getColorメソッド(Java) → FillColorプロパティ(C#)
というようにマッピングしている。名前に「Invoke」が付かないFillColorは読み取り専用プロパティだ。他のInvoke系メソッドも同様に、値を取得するためのプロパティが用意されている。

 なお、この命名ルールは、GoogleMapAPIについてであって、Xamarin.Android全体で統一されている保証はないことを覚えておいてほしい。

3. ポリゴンを描画する

 続いて、[Polygon]ボタンを押した時にポリゴンを追加するコードを、以下のように記述する。

C#
[Activity(Label = "GoogleMapSample", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : Activity
{
  protected override void OnCreate(Bundle bundle)
  {
    base.OnCreate(bundle);

    ……省略……

    FindViewById<Button>(Resource.Id.buttonPolygon).Click += (sender, e) => 
    {
      map.AddPolygon(new PolygonOptions()
        .Add(new LatLng(35.680d, 139.765d)) // 東京駅付近
        .Add(new LatLng(35.629d, 139.737d)) // 品川駅付近
        .Add(new LatLng(35.690d, 139.699d)) // 新宿駅付近
        .Add(new LatLng(35.680d, 139.765d)) // 東京駅付近
        .InvokeFillColor(Color.Magenta)
        .InvokeStrokeColor(Color.Red)
        .InvokeStrokeWidth(3f)
      );
    };
  }
}
[Polygon]ボタンを押した時に、ポリゴンを追加するコード(MainActivity.cs)

 ポリゴンの追加は、ラインのときのmap.AddPolylinePolylineOptionの代わりにmap.AddPolygonメソッドとPolygonOptionオブジェクトを使う。このオブジェクトに対するパラメーターでは、緯度経度の指定方法はラインの場合と同じだが、「閉じた座標群」が必要なので、最終点は開始点と同じ緯度経度を設定する。また、「面」であるので、塗りつぶしの色(InvokeFillColor)と、枠線の色(InvokeStrokeColor)、枠線の幅(InvokeStrokeWidth)が設定できる。

4. 円を描画する

 最後に、[Circle]ボタンを押した時に円を追加するコードを、以下のように記述する。

C#
[Activity(Label = "GoogleMapSample", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : Activity
{
  protected override void OnCreate(Bundle bundle)
  {
    base.OnCreate(bundle);

    ……省略……

    FindViewById<Button>(Resource.Id.buttonCircle).Click += (sender, e) => 
    {
      map.AddCircle(new CircleOptions()
        .InvokeCenter(new LatLng(35.697d, 139.773d)) // 秋葉原駅付近
        .InvokeRadius(2000)
        .InvokeFillColor(Color.Yellow)
        .InvokeStrokeColor(Color.YellowGreen)
        .InvokeStrokeWidth(2f)
      );
    };
  }
}
[Circle]ボタンを押した時に、円を追加するコード(MainActivity.cs)

 円の追加は、map.AddCircleメソッドとCircleOptionオブジェクトを使う。このオブジェクトに対するパラメーターとしては、円の中心の緯度経度と半径(Radius、単位:m)、塗りつぶしと線の色、および線幅を指定している。

5. 図形の削除

 図形の削除は、map.AddPolylinemap.AddPolygonmap.AddCircleメソッドなどを呼び出すと返却されるオブジェクトを使用して行う。

 具体的には、「円が追加されていたらそれを削除する、存在しなければ追加する」というコードは、以下のようになる。

C#
[Activity(Label = "GoogleMapSample", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : Activity
{
  protected override void OnCreate(Bundle bundle)
  {
    base.OnCreate(bundle);

    ……省略……

    Circle circle = null;

    FindViewById<Button>(Resource.Id.buttonCircle).Click += (sender, e) => 
    {
      if (circle != null) {
        circle.Remove();
        circle = null;
      } 
      else {
        circle = map.AddCircle(new CircleOptions()
          .InvokeCenter(new LatLng(35.697d, 139.773d)) // 秋葉原駅付近
          .InvokeRadius(2000)
          .InvokeFillColor(Color.Yellow)
          .InvokeStrokeColor(Color.YellowGreen)
          .InvokeStrokeWidth(2f)
        );
      }
    };
  }
}
[Circle]ボタンを押した時に、円を削除もしくは追加するコード(MainActivity.cs)

 map.AddCircleメソッドを呼び出すと、Circleオブジェクトが返却される。このCircleオブジェクトのRemoveメソッドを呼び出すと、その図形が削除される。

 ここまでのプログラムを実行すると、図2のようになる。

図2 プログラムの実行結果(図形の表示)

 [Line]/[Polygon]/[Circle]ボタンを押すと、それぞれ「ライン」「ポリゴン」「円」が地図に追加される。[Circle]ボタンは、押すごとに円の追加/削除が繰り返される。

まとめ

 GoogleMapAPIでの図形の追加と削除について解説した。今回紹介した[Line]/[Polygon]/[Circle]それぞれのクラスのAPIは、以下に示すネイティブのAPIリファレンスを参照されたい。

 次回は、GoogleMapAPIでマーカーを使用する方法について解説する予定だ。

※以下では、本稿の前後を合わせて5回分(第20回~第24回)のみ表示しています。
 連載の全タイトルを参照するには、[この記事の連載 INDEX]を参照してください。

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アプリで地図の表示位置や種類を変更する方法、ジェスチャの有効/無効を切り替える方法などを説明する。

22. 【現在、表示中】≫ Xamarin.Androidで地図に図形を表示するには?(Google Maps使用)

「Google Maps Android API v2」を使って、Xamarin.Androidアプリで地図上にライン/ポリゴン/円などの図形を表示する方法を解説する。

23. Xamarin.Androidで地図にマーカーを表示するには?(Google Maps使用)

「Google Maps Android API v2」を使って、Xamarin.Androidアプリで地図上にマーカーや吹き出しを表示する方法を解説する。

24. Xamarin Studio で画面を分割するには?(ショートカットキー情報あり)[Mac&Win対応]

Xamarin Studioの新機能として、コードエディターを左右の領域に分割して表示できるようになった。マウスとショートカットキーによる操作方法を説明する。

イベント情報(メディアスポンサーです)

Twitterでつぶやこう!


Build Insider賛同企業・団体

Build Insiderは、以下の企業・団体の支援を受けて活動しています(募集概要)。

ゴールドレベル

  • グレープシティ株式会社
  • 日本マイクロソフト株式会社