Xamarin.iOSで地図にTileを追加したりしてみる
前回
のXamarin.iOS版です。(Xamarin.Formsではありませんよ)
iOSで標準の地図コントロールと言えばMKMapViewだと思うのでこれを使っていきます。当然TMSです。
とりあえずこんな感じで。(StoryboardにMKMapViewを置いただけ)
UWPよりきれいですね
Open Street Mapを追加する
MKTileOverlay
を使います。コンストラクタにURLテンプレートを渡せばいいです。
Map.Delegate = new MapDelegate(); var osmTileOverlay = new MKTileOverlay("http://tile.openstreetmap.org/{z}/{x}/{y}.png"); Map.InsertOverlay(osmTileOverlay, 0, MKOverlayLevel.AboveLabels); class MapDelegate : MKMapViewDelegate { public override MKOverlayRenderer OverlayRenderer(MKMapView mapView, IMKOverlay overlay) { if (overlay is MKTileOverlay) { return new MKTileOverlayRenderer((MKTileOverlay)overlay); } return base.OverlayRenderer(mapView, overlay); } }
Map
はMKMapViewのインスタンスです。
URLテンプレートは、UWPの時は{zoomlevel}
だったところが{z}
に変わっているだけですね。
Overlayを追加する時はMapDelegateにOverlayRendererを追加しないといけないのが面倒だし少しはまるところですね。
iOS9(だっけ?)からはこれだけではまだ表示できないという罠があります。
上のソースのURLを見るとhttp
ですね、これダメなんですよね・・。
とりあえずInfo.plistに下を追加しておきましょう。
<key>NSAppTransportSecurity</key> <dict> <key>NSExceptionDomains</key> <dict> <key>tile.openstreetmap.org</key> <dict> <key>NSExceptionAllowsInsecureHTTPLoads</key> <true/> <key>NSIncludesSubdomains</key> <true/> </dict> </dict> </dict>
実行すると
こんな感じになります
既定の地図を変更する
iOSでもデフォルトの地図を入れ替えることができます。先ほどのソースに一行追加するだけ
var osmTileOverlay = new MKTileOverlay("http://tile.openstreetmap.org/{z}/{x}/{y}.png"); osmTileOverlay.CanReplaceMapContent = true; Map.InsertOverlay(osmTileOverlay, 0, MKOverlayLevel.AboveLabels);
osmTileOverlay.CanReplaceMapContent = true;
です。
カスタムソースのタイルを追加
前回と同じように半透明のタイルを重ねます
class CustomTileOverlay : MKTileOverlay { public override void LoadTileAtPath(MKTileOverlayPath path, MKTileOverlayLoadTileCompletionHandler result) { UIGraphics.BeginImageContext(TileSize); var a = 0.5f; var r = ((path.X + path.Y) % 3) == 0 ? 1 : 0; var g = ((path.X + path.Y + 1) % 3) == 0 ? 1 : 0; var b = ((path.X + path.Y + 2) % 3) == 0 ? 1 : 0; var fill = new CGColor(r, g, b, a); using (var graphic = UIGraphics.GetCurrentContext()) { graphic.SetFillColor(fill); graphic.FillRect(new CGRect(0, 0, TileSize.Width, TileSize.Height)); } var tileImage = UIGraphics.GetImageFromCurrentImageContext(); UIGraphics.EndImageContext(); result(tileImage.AsPNG(), new NSError()); } }
MKTileOverlay
を継承したクラスを作ってLoadTileAtPath
でビットマップを作って返すようにします。
あとはこれを追加するだけ。
var customTileOverlay = new CustomTileOverlay(); Map.InsertOverlay(customTileOverlay, 0, MKOverlayLevel.AboveLabels);
実行すると
多少重いですができました。
多分続きます