前回の記事でご紹介したGoogleMapsですが、初期表示でローマがフォーカスされてしまいます。

現場でこのケースに遭遇した時は「全ての道はローマに通ず」とか言って楽しんでましたが、いざカスタマイズしようとして結構苦労した記憶があります。

ちなみにこれ、今の今まで知らなかったんですが、Xamarin標準のMapsがローマをフォーカスしてしまうらしいですね。

(参考:Summary of Chapter 28. Location and maps

今回はPrismを利用してMVVMパターンによる暫定解決策(回避策の方が正しいか?)をご紹介します。

前回のプロジェクトをそのまま使っていきます。

『Xamarin.Forms.GoogleMaps.Bindings』のNugetパッケージ取得

まず『Xamarin.Forms.GoogleMaps』ですが、そのままではMVVMパターンでの実装が不可能です。

※バインディングできません、MVVMパターンにできません。

開発の際は最初愕然としましたが、調べてみたらなんとデータバインディング用のパッケージをリリースしていらっしゃる方がいました。

(参考:Xamarin.Forms.GoogleMaps用のBinding拡張ライブラリをリリースしました

ということで早速パッケージをインストールしていきます。

作成者の欄を見て頂くと『Xamarin.Forms.GoogleMaps』の開発者である「amay077」さんの名前も載っていますね。

インストール後はAndroidプロジェクトのMainActivityにパッケージの初期化コードを追加します。

using Android.App;
using Android.Content.PM;
using Android.OS;
using Prism;
using Prism.Ioc;

namespace SampleAndroid7._1.Droid
{
    [Activity(Label = "SampleAndroid7._1", Icon = "@mipmap/ic_launcher", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
    public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
    {
        protected override void OnCreate(Bundle bundle)
        {
            TabLayoutResource = Resource.Layout.Tabbar;
            ToolbarResource = Resource.Layout.Toolbar;

            base.OnCreate(bundle);

            global::Xamarin.Forms.Forms.Init(this, bundle);

            // 追加したコード
            Xamarin.FormsGoogleMaps.Init(this, bundle);
            Xamarin.FormsGoogleMapsBindings.Init();

            LoadApplication(new App(new AndroidInitializer()));
        }
    }

    public class AndroidInitializer : IPlatformInitializer
    {
        public void RegisterTypes(IContainerRegistry container)
        {
            // Register any platform specific implementations
        }
    }
}

XAMLのGoogleMapsにビヘイビアを追加

GoogleMapsの表示位置を変更するには「MoveToRegionBehavior」を使用します。

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:maps="clr-namespace:Xamarin.Forms.GoogleMaps;assembly=Xamarin.Forms.GoogleMaps"
             xmlns:bindings="clr-namespace:Xamarin.Forms.GoogleMaps.Bindings;assembly=Xamarin.Forms.GoogleMaps.Bindings"
             x:Class="SampleAndroid7._1.Views.MainPage"
             Title="{Binding Title}">

    <maps:Map>
        <maps:Map.Behaviors>
            <bindings:MoveToRegionBehavior Request="{Binding MoveToRegionRequest}"/>
        </maps:Map.Behaviors>
    </maps:Map>

</ContentPage>

余談ですが、開発当初は「MoveCameraBehavior」が表示位置の変更だろうと思ってかなり苦労した記憶があります。

画面遷移時に表示位置の変更を行う

ここからが今回の記事の本旨になりますが、前述の通りGoogleMapsの初期表示位置はローマになります。

これをどう解決していくか、というところで最初はViewModelのコンストラクタでやっちゃおうかと思ったんですが、そもそも画面が初期化されていない状態ではできないんですよね…。

ということで『Prism』の「OnNavigatedTo」メソッドを利用しました。

using Prism.Navigation;
using Xamarin.Forms.GoogleMaps;
using Xamarin.Forms.GoogleMaps.Bindings;

namespace SampleAndroid7._1.ViewModels
{
    public class MainPageViewModel : ViewModelBase
    {
        // 表示位置移動用
        public MoveToRegionRequest MoveToRegionRequest { get; } = new MoveToRegionRequest();

        /// <summary>
        /// コンストラクタ
        /// </summary>
        /// <param name="navigationService"></param>
        public MainPageViewModel(INavigationService navigationService)
            : base(navigationService)
        {
            Title = "Main Page";
        }

        /// <summary>
        /// 画面遷移時処理
        /// </summary>
        /// <param name="parameters"></param>
        public override void OnNavigatedTo(NavigationParameters parameters)
        {
            base.OnNavigatedTo(parameters);

            // 画面遷移後に現在位置へ移動する
            MoveToCurrentLocation();
        }

        /// <summary>
        /// 現在位置へ移動するメソッド
        /// </summary>
        public void MoveToCurrentLocation()
        {
            // TODO:現在地点の座標取得(下記は兵庫県明石市)
            MoveToRegionRequest.MoveToRegion(new MapSpan(new Position(35.000000d, 135.000000d), 0.3d, 0.3d));
        }
    }
}

「OnNavigatedTo」メソッドの簡単な説明をしておくと、「当該画面遷移時の処理」で「コンストラクタの後に動き」ます。

(参考:Prism for Xamarin.Forms Navigationイベント詳細 NavigationPage編

実行してみると初期表示位置がローマから兵庫県へと変わりました。

※明石市じゃないことにびっくりしたのは内緒です。

まとめ

『Xamarin.Forms.GoogleMaps』でローマが初期表示されてしまう問題のMVVMパターンによる回避策として

『Prism』の「OnNavigatedTo」メソッドで初期表示位置を変更する。

MVVMパターンでの実装を行うには『Xamarin.Forms.GoogleMaps.Bindings』を利用しましょう。

以上です。

スポンサーリンク