Xamarin逆引きTips
Xamarin.Androidで地図を操作するには?(Google Maps使用)
「Google Maps Android API v2」を使って、Xamarin.Androidアプリで地図の表示位置や種類を変更する方法、ジェスチャの有効/無効を切り替える方法などを説明する。
前回に引き続き、Xamarin.AndroidアプリでGoogle Maps Android API v2(以下、「GoogleMapAPI」と表記)を使用する。今回は、地図の位置の変更や、地図種類の変更などの各種設定について解説する。
「Tips:Xamarin.Androidで地図を表示するには?(Google Maps使用)」の続きとして解説するので、プロジェクトの準備は前回を参照してほしい。
1. 地図の位置を変更する
GoogleMapAPIで地図を指定の位置に移動させるには、以下のような方法がある。
- 中心位置(緯度経度)を指定
- 範囲(南西と北東の緯度経度)を指定
- カメラ(緯度経度、方位、傾き)を指定
それぞれを試すために、まずは画面にボタンを3つ用意する。
前回終了時点で、Main.axml
ファイルを開くと、以下のようになっているはずだ。
<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.google.android.gms.maps.MapFragment" />
|
これを、以下のように修正する。
1
2
3
4
5
6
7
8
9
10
1
12
13
14
15
16
17
2
19
20
21
22
23
24
3
26
27
28
29
30
31
|
<?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デザイナーで確認すると、図1のようになる。
前回は画面いっぱいに地図を配置しただけだったが、今回はそれに加えてボタンを配置するため、全体をRelativeLayout
で囲み、その全体にMapFragment
を配置し、1~3で、それぞれ[Center][Bounds][Camera]ボタンを配置している。
【コラム】レイアウト変更後にアプリケーションが落ちる場合
筆者の経験による事象だが、上記のようなFragmentを含むレイアウトXMLを変更し、アプリケーションをビルドして実行すると、エラーでアプリケーションが落ちることがあった。このような場合は、メニューバーの[ビルド]-[すべてクリーン]を実行してから再度ビルド→実行すると正しく動作する。
中心位置(緯度経度)を指定
MainActivity.cs
ファイルを、以下のように修正する。
using Android.Gms.Maps;
using Android.Gms.Maps.Model;
……省略……
[Activity(Label = "GoogleMapSample", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : Activity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
var mapFragment = (MapFragment)FragmentManager.FindFragmentById(Resource.Id.map);
var map = mapFragment.Map; // <--1
FindViewById<Button>(Resource.Id.buttonCenter).Click += (sender, e) =>
{
map.AnimateCamera(CameraUpdateFactory.NewLatLng(
new LatLng(35.68d, 139.76d))); // 東京駅付近 <--2
};
}
}
|
[Center]ボタンを押した時の処理を上記のように記述する。
1で、画面に配置したMapFragment
から、実際の「地図」を表すGoogleMap
オブジェクトを取得し、変数map
に代入する。
GoogleMapAPIでは、GoogleMap
オブジェクトのAnimateCamera
メソッドにCameraUpdate
クラスのインスタンスを渡すことで、目的の位置へ移動する。2では、CameraUpdateFactory.NewLatLng
メソッドで緯度経度からCameraUpdate
オブジェクトを生成し、それを引数にmap.AnimateCamera
メソッドを呼び出している。なお、AnimateCamera
は、メソッド名の通りアニメーションしながら移動するが、アニメーションさせたくない場合はGoogleMap
オブジェクトのMoveCamera
メソッドを使用する。こちらも引数はCameraUpdate
だ。
範囲(南西と北東の緯度経度)を指定
MainActivity.cs
ファイルを、以下のように修正する。
[Activity(Label = "GoogleMapSample", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : Activity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
……省略……
FindViewById<Button>(Resource.Id.buttonBounds).Click += (sender, e) =>
{
var bounds = LatLngBounds.InvokeBuilder()
.Include(new LatLng(35.4661d,139.6227d)) // 横浜駅
.Include(new LatLng(35.4713d,139.6274d)) // 神奈川駅
.Build(); //<--1
map.AnimateCamera(CameraUpdateFactory.NewLatLngBounds(bounds, 100)); //<--2
};
}
}
|
[Bounds]ボタンを押した時の処理を上記のように記述する。
範囲指定でもGoogleMap.AnimateCamera
メソッドを使用する。引数として渡すCameraUpdateの生成方法が異なるだけだ。あらかじめ緯度経度の範囲を示すLatLngBounds
オブジェクトを用意しておき、それを指定してCameraUpdateFactory.NewLatLngBounds
メソッドを呼び出してCameraUpdate
を生成する。NewLatLngBounds
メソッドの第2引数は画面に設ける余白で、ここでは100pxを指定している。あとはCameraUpdate
をmap.AnimateCamera
メソッドに渡すだけだ。
カメラ(緯度経度、方位、傾き)を指定
MainActivity.cs
ファイルを、以下のように修正する。
[Activity(Label = "GoogleMapSample", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : Activity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
……省略……
FindViewById<Button>(Resource.Id.buttonCamera).Click += (sender, e) =>
{
map.AnimateCamera(CameraUpdateFactory.NewCameraPosition(
new CameraPosition(
new LatLng(35.710063d,139.8107d), // 東京スカイツリー(中心位置)
17f, // ズームレベル
45f, // 方位
30f))); // 傾き
};
}
}
|
[Camera]ボタンを押した時の処理を上記のように記述する。
カメラを使用する際は、CameraPosition
オブジェクトを生成し、それを指定してCameraUpdateFactory.NewCameraPosition
メソッドを呼び出し、CameraUpdate
を生成する。CameraPosition
は、「中心位置」「ズームレベル(=地図の表示倍率)」「方位」「視点の傾き」を指定する。上記の例では、「東京スカイツリー」で、「時計周りに45度回転」し、「視点を30度手前に傾けた」位置となる。方位については、自分が時計回りに45度回転するので、地図上のコンパスは反時計周りに45度回転する。
ここまでのプログラムを実行すると、それぞれ以下の画面のようになる。
2. 地図の種類の変更、ジェスチャの有効/無効の切り替えなど
その他の一般的な機能をまとめて紹介する。まずはMainActivity.cs
ファイルを、以下のように追加する。
[Activity(Label = "GoogleMapSample", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : Activity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
var mapFragment = (MapFragment)FragmentManager.FindFragmentById(Resource.Id.map);
var map = mapFragment.Map;
map.MapType = GoogleMap.MapTypeSatellite ; // 衛星画像 <--1
map.MyLocationEnabled = true; // 現在位置を表示する <--2
map.BuildingsEnabled = false; // 建物を3D表示しない <--3
map.SetIndoorEnabled(false); // インドアマップを表示しない <--4
map.UiSettings.ScrollGesturesEnabled = false; // ジェスチャでのスクロールを許可しない <--5
map.UiSettings.ZoomGesturesEnabled = false; // ジェスチャでのズームを許可しない <--6
map.UiSettings.RotateGesturesEnabled = false; // ジェスチャでの回転を許可しない <--7
map.UiSettings.TiltGesturesEnabled = false; // ジェスチャでの視点変更を許可しない <--8
map.UiSettings.CompassEnabled = false; // コンパスを表示しない <--9
map.UiSettings.IndoorLevelPickerEnabled = false; // インドアマップの階数を表示しない <--10
map.UiSettings.MyLocationButtonEnabled = false; // 現在位置ボタンを表示しない <--11
map.UiSettings.ZoomControlsEnabled = false; // ズームボタンを表示しない <--12
}
}
|
地図の種類の変更
1は、表示する地図の種類を「衛星画像(GoogleMap.MapTypeSatellite
)」に変更するコードだ。他に「通常(GoogleMap.MapTypeNormal
)」や「通常+衛星画像(GoogleMap.MapTypeHybrid
)」、「地形図(GoogleMap.MapTypeTerrain
)」が使用できる。
現在位置の表示切り替え
2は、現在位置を表示するためのコードだ。true
を設定すると、GPSにより取得した現在の位置を、コーディングを行わなくても地図上に表示できる。
建物を3D表示に切り替え
3は、建物を3Dで表示しないようにするコードだ。前出の東京スカイツリーなどは既定では3Dで表示されるが、これをfalse
にすると2Dの表示になる。
インドアマップの有効/無効の切り替え
GoogleMapAPIには、インドアマップと呼ばれる、建物内部の地図を表示する機能があり、主に駅などで利用できる。4は、このインドアマップを表示しないようにするコードだ(ちなみにこの項目だけプロパティでなくSetIndoorEnabled
メソッドなのは、今後、修正されるのではないかと推測する)。
ジェスチャ操作の有効/無効の切り替え
5、6、7、8はそれぞれ、ジェスチャでのスクロール、ズーム、回転、視点変更を無効にするためのコードだ。
地図上のコントロールの表示切り替え
9、10、11、12はそれぞれ、地図上に表示されているコンパス、インドアマップの階数(4が有効なときに表示される)、現在位置ボタン(2が有効なときに表示される)、ズームボタンを非表示にするためのコードだ。
地図の種類を「衛星画像」、現在位置を「表示する」としたプログラムを実行すると、図3のようになる。
まとめ
Xamarin.AndroidでのGoogleMapAPIの基本的な使い方を解説した。Xamarin.iOSでのMapKitの使用と同じく、AndroidネイティブのGoogleMapAPIのAPIは、ほぼそのままXamarin.Androidで使えるので、開発の際には、ネイティブのGoogleMapAPIのAPIリファレンス(英語)を参照されたい。
また、Xamarin.Android用のGoogleMapAPIライブラリは、ネイティブのライブラリをXamarinで利用するための技術「Binding」で実現されている。ソースコードが「GitHub: mono/monodroid-bindings」で公開されているので、興味のある人は自力でビルドしてみるのもよいだろう。
次回以降は、GoogleMapAPIで図形を描く方法や、マーカーを使用する方法について解説する予定だ。
※以下では、本稿の前後を合わせて5回分(第19回~第23回)のみ表示しています。
連載の全タイトルを参照するには、[この記事の連載 INDEX]を参照してください。
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アプリで地図の表示位置や種類を変更する方法、ジェスチャの有効/無効を切り替える方法などを説明する。
22. Xamarin.Androidで地図に図形を表示するには?(Google Maps使用)
「Google Maps Android API v2」を使って、Xamarin.Androidアプリで地図上にライン/ポリゴン/円などの図形を表示する方法を解説する。
23. Xamarin.Androidで地図にマーカーを表示するには?(Google Maps使用)
「Google Maps Android API v2」を使って、Xamarin.Androidアプリで地図上にマーカーや吹き出しを表示する方法を解説する。