Xamarin.Form 使用Google地圖

李政輝C.H. Lee

  • 恆逸教育訓練中心-資深講師
  • 技術分類:App開發

 

 

Visual Studio Xamarin.Form是一個產生雙平台(ANDROID/IOS)原生的成熟開發專案,即使鬆散偶合MAUI的出現, Xamarin.Form使用緊密散偶的開發方式直覺的與ANDROID/IOS手機的使用者體驗完美結合。在這個文章中,我將製作一個APP 來顯示GOOGLE地圖,並結合大數據CSV資料加入至PIN標示點。

技術主題:
  1. 透過MainPage內容頁,產生Menu對應至3個建立的內容頁
  2. 透過Map內容頁,顯示Google Map
  3. 透過PinPage內容頁,在地圖加入Pin
  4. 透過Covid19Page內容頁,加入定位功能做為地圖的中心點,同時透過Data.GOV取出公費COVID-19家用快篩試劑診所名單的CSV檔並將其資料產生Pin

預設畫面預覽:
  1. MainPage內容頁(Menu)
  2. MainPage內容頁(Map-顯示Google Map)
  3. PinPage內容頁(Pins-在地圖加入Pin)
  4. Covid19Page內容頁(快篩試劑地圖-公費COVID-19家用快篩試劑診所名單)


主題1:透過MainPage內容頁,產生Menu對應至3個建立的內容頁


  • 1.1建立新專案,選擇:行動應用程式式(Xamarin.Forms),按「下一步」


    專案名稱:GoogleMaps,按「建立」。

  • 1.2 在App.xaml啟用NavigationPage;

    App.xaml.cs

            
       public App()
          {
        InitializeComponent();
        //1.2
        //MainPage = new MainPage();
        MainPage = new NavigationPage(newMainPage());
        }
        
    
  • 1.3 在MainPage.xaml使用TableView加入MENU目錄,對應至3個建立的內容頁

  • 1.4建立MapPage.xaml

    專案(按右鍵) 加入 新增項目。


    Xamarin.Forms 內容頁面 名稱:MapPage.xaml 按「新增」

  • 1.5重覆上一步驟,加入PinPage.xaml

  • 1.6重覆上一步驟,加入Covid19Page.xaml

  • 1.7在MainPage加入TableView及TableCell,做為目錄清單。透過TableCell的CommandParameter連結三個內容頁。

    MainPage.xaml <?xml version="1.0" encoding= "utf-8" ?>

      <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
                         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                         x:Class="GoogleMaps.MainPage"
                         xmlns:local="clr-namespace:GoogleMaps">
                <TableView Intent="Menu">
                    <TableRoot>
                        <TableSection>
                            <TextCell Text="Map"
                                      Detail="顯示Google Map"
                                      Command="{Binding NavigateCommand}"
                                      CommandParameter="{x:Type local:MapPage}" />
                            <TextCell Text="Pins"
                                      Detail="在地圖加入Pin"
                                      Command="{Binding NavigateCommand}"
                                      CommandParameter="{x:Type local:PinPage}" />
                            <TextCell Text="快篩試劑地圖"
                                      Detail="公費COVID-19家用快篩試劑診所名單"
                                      Command="{Binding NavigateCommand}"
                                      CommandParameter="{x:Type local:Covid19Page}" />
            
                        </TableSection>
                    </TableRoot>
                </TableView>
            
        </ContentPage>
            
  • 1.8在MainPage.cs透過NavigateCommand將內容頁Push至NavigationPage。

    MainPage.cs

      public partial class MainPage : ContentPage
            {
            public ICommand NavigateCommand { get; set; }
            public MainPage()
            {
                InitializeComponent();
    
                NavigateCommand = new Command<Type>(async (Type pageType) =>
                {
                    Page page = (Page)Activator.CreateInstance(pageType);
                    await Navigation.PushAsync(page);
                });
    
                BindingContext = this;
            }
        }
    


主題2:透過Map內容頁,顯示Google Map


  • 2.1 將NuGet 套件:Xamarin.Forms.Maps 新增至方案中

  • 2.2 安裝Xamarin.Forms.Maps NuGet 套件之後,必須在每個平台專案中初始化它


    Android專案的 MainActivity.cs將 Xamarin.FormsMaps.Init(this, savedInstanceState);
    加至 global::Xamarin.Forms.Forms.Init(this, savedInstanceState);的後面

    MainActivity.cs

        
        protected void override OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
            Xamarin.Essentials.Platform.Init(this, savedInstanceState);
            global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
            Xamarin.FormsMaps.Init(this, savedInstanceState);
            LoadApplication(new App());
        }
          

    iOS專案的AppDelegate.cs 將Xamarin.FormsMaps.Init();加至global::Xamarin.Forms.Forms.Init();的後面

    AppDelegate.cs

       public override bool FinishedLaunching(UIApplication app, NSDictionary options) 
       {
           global::Xamarin.Forms.Forms.Init();
           Xamarin.FormsMaps.Init();
           LoadApplication(new App());
           return base.FinishedLaunching(app, options);
       }
        
  • 2.3 在iOS專案上,存取使用者的位置需要已授與應用程式的位置許可權。

    在iOS上顯示地圖並與其互動不需要任何其他設定。不過,若要存取位置服務,您必須在Info.plist中設定下列金鑰:


    Info.plist加入這些索引鍵的 XML 標記,值是字串類型

    <key>NSLocationAlwaysUsageDescription</key >
    <string>Can we use your location at all times?</string >
    <key>NSLocationWhenInUseUsageDescription</key >
    <string>Can we use your location when your application is being used?</string >
    <key>NSLocationAlwaysAndWhenInUseUsageDescription</key >
    <string>Can we use your location at all times?</string >
  • 2.4 在Android 專案上,存取使用者的位置需要已授與應用程式的位置許可權。

    在 Android 上顯示和互動地圖的設定程式如下:

    1. 取得 Google 地圖 API 金鑰,並將其新增至資訊清單。 在Google Developer Console

      https://console.developers.google.com/

      建立一個專案,然後加入API
      • Maps SDK for Android
      • Maps SDK for iOS
      取得 Google 地圖 API 金鑰,並將其新增至資訊清單。
      • 憑證 建立憑證 API金鑰
      取得 API 金鑰之後,必須在Android專案Properties/AndroidManifest.xml檔案的元素內 <application> 新增它:
        
          <application...>
             
            <!-- 取得 Google 地圖 API 金鑰 -->
            
            <meta-data android:name="com.google.android.geo.API_KEY" android:value="AIzaSyACo9xxxxxxxxxxxxxUcihwMyiASw" />
      
           </application>
                  

    2. 在Android專案Properties/AndroidManifest.xml檔案資訊清單中指定 Google Play 服務版本號碼。

      
          <application...>
            
            <!-- 指定 Google Play 服務版本號碼 -->
            
            <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />
      
          </application>
                  

    3. 在資訊清單中指定 Apache HTTP 舊版程式庫的需求。
      Xamarin.Forms如果您的應用程式以 API 28 或更高版本為目標,您必須在<application>AndroidManifest.xml的元素內新增下列宣告:

      
          <application...>
            
            <!-- 如果您的應用程式以 API 28 (Android 9.0)或更高版本為目標必須新增下列宣告 -->
           
            <uses-library android:name="org.apache.http.legacy" android:required="false" />
      
          </application>
                  

    4. 在資訊清單中指定位置許可權。
      如果您的應用程式需要存取使用者的位置,您必須藉由將或許可權新增ACCESS_COARSE_LOCATION 至資訊清單(或兩者),以要求許可權,做為專案的子系<manifest>:ACCESS_FINE_LOCATION

      
          <manifest xmlns:.....>
              
               <!-- 需要存取使用者的位置必須宣告指定位置許可權 -->
      
              <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
              
              <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
      
          </manifest>
                  

      許可權 ACCESS_COARSE_LOCATION 可讓 API 使用 WiFi 或行動資料,或兩者來判斷裝置的位置。 許可權 ACCESS_FINE_LOCATION 可讓 API 使用全域定位系統 (GPS) 、WiFi 或行動資料,以盡可能判斷位置。

    5. 要求類別中的 MainActivity 執行時間位置許可權。
      如果您的應用程式是以 API 23 或更新版本為目標,而且需要存取使用者的位置,則必須檢查它是否具有執行時間的必要許可權,並在沒有時要求它。 執行下列工作即可達成這點:

      • 在類別中 MainActivity ,新增下欄欄位:
      • 在類別中 MainActivity ,新增下列 OnStart 覆寫:
      • 如果應用程式是以 API 23 或更新版本為目標,此程式碼會執行許可權的 AccessFineLocation 執行時間許可權檢查。 如果未授與許可權,呼叫 方法就會提出 RequestPermissions 許可權要求。

      Android專案的MainActivity.cs

      //在類別中 MainActivity ,新增下欄欄位:
      const int RequestLocationId = 0;
      readonly string[]  LocationPermissions =
      {
               //using Android;
               Manifest.Permission.AccessCoarseLocation,
               Manifest.Permission.AccessFineLocation
      };
      //在類別中 MainActivity ,新增下列 OnStart 覆寫:
      protected override void OnStart()
      {
           base.OnStart();
      
           if ((int)Build.VERSION.SdkInt >= 23)
            {
                  if (CheckSelfPermission(Manifest.Permission.AccessFineLocation) != Permission.Granted)
                  {
                      RequestPermissions(LocationPermissions, RequestLocationId);
                  }
                  else
                  {
                      // Permissions already granted - display a message.
                  }
             }
             }
      
      //如果應用程式是以 API 23 或更新版本為目標,此程式碼會執行許可權的 AccessFineLocation 執行時間許可權檢查。 如果未授與許可權,呼叫 方法就會提出 RequestPermissions 許可權要求。
      public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
      {
                  Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
      
      //base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
          if (requestCode == RequestLocationId)
              {
                   if ((grantResults.Length == 1) && (grantResults[0] == (int)Permission.Granted))
                       {
                          // Permissions granted - display a message.
                       }
                  else {  
                          // Permissions denied - display a message.
                       }
              }
           else
              {
                  base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
              }
          }
      
  • 2.5 在MapPage內容頁新增Map控制項:

    MapPage.xaml

    <?xml version="1.0" encoding="utf-8" ?>
      <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
        x:Class="GoogleMaps.MapPage"
        xmlns:maps="clr-namespace:Xamarin.Forms.Maps;assembly=Xamarin.Forms.Maps"
        Title="Map">
      <ContentPage.Content>
        <StackLayout> 
      
        <!--顯示地圖-->
           <!--
              MapType :
              Street 指定將會顯示街道地圖。
              Satellite 指定將會顯示包含衛星影像的地圖。
              Hybrid 會指定將顯示結合街道和衛星資料的地圖。
              TrafficEnabled="true" 顯示流量資料
              IsShowingUser="true" 顯示使用者的位置
              OnMapClicked 事件處理常式:會輸出代表點選地圖位置的緯度和經度。
           -->
      
       <maps:Map x:Name="map" MapType="Street"
             MapClicked="OnMapClicked">
           <x:Arguments>
               <maps:MapSpan>
                   <x:Arguments>
                       <maps:Position>
                           <x:Arguments>
                               <!--在地圖上顯示特定位置為中心-->
                               <x:Double>25.052992</x:Double>
                               <x:Double>121.544633</x:Double>
                           </x:Arguments>
                       </maps:Position>
                       
                       <!--地圖縮放比例-->
                       <x:Double>0.1</x:Double>
                       <x:Double>0.1</x:Double>
                   </x:Arguments>
               </maps:MapSpan>
           </x:Arguments>
        </maps:Map>
        
        </StackLayout>
      </ContentPage.Content>
      </ContentPage>
    
  • 2.6 在MapPage.xaml.cs 加入OnMapClicked事件委派

    MapPage.xaml.cs

    using System;
        using System.Collections.Generic;
        using System.Linq;
        using System.Text;
        using System.Threading.Tasks;
        
        using Xamarin.Forms;
        using Xamarin.Forms.Maps;
        using Xamarin.Forms.Xaml;
        
        namespace GoogleMaps
        {
            [XamlCompilation(XamlCompilationOptions.Compile)]
            public partial class MapPage : ContentPage
            {
                public MapPage()
                {
                    InitializeComponent();
                }
                async  void OnMapClicked(object sender, MapClickedEventArgs e)
                {
                    await DisplayAlert("經緯度位置", $"您點選的位置是: {e.Position.Latitude}, {e.Position.Longitude}" ,"OK");
                }
            }
        }
        
  • 2.7 測試



主題3. 透過PinPage內容頁,在地圖加入Pin


控制項 Xamarin.Forms.Map 允許使用物件標記位置:Pin
Pin是點選時開啟資訊視窗的地圖標記:

類別 Pin 具有下列屬性:

  • Label類型為string,這通常代表Pin標題。
  • Address類型為string,這通常代表Pin釘選位置的位址。 不過,它可以是任何 string 內容,而不只是位址。
  • Position類型為Position ,表示Pin的緯度和經度。
  • Type類型為PinType列舉 ,表示Pin的類型。
  • 3.1 在PinPage.xaml加入Pin

    PinPage.xaml

    <?xml version="1.0" encoding="utf-8" ?>
        <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
        x:Class="GoogleMaps.PinPage"
        xmlns:maps="clr-namespace:Xamarin.Forms.Maps;assembly=Xamarin.Forms.Maps"
        Title="Pins">
    <ContentPage.Content>
    <StackLayout>
       <maps:Map x:Name="map" MapType="Street">
           <x:Arguments>
               <maps:MapSpan>
                   <x:Arguments>
                       <maps:Position>
                           <x:Arguments>
                               <!-->在地圖上顯示特定位置為中心-->
                               <x:Double>25.042171 </x:Double>
                               <x:Double>121.566376</x:Double>
                           </x:Arguments>
                       </maps:Position>
                       <!--地圖縮放比例-->
                       <x:Double>0.1</x:Double>
                       <x:Double>0.1</x:Double>
                   </x:Arguments>
               </maps:MapSpan>
           </x:Arguments>
           <maps:Map.Pins>
               <maps:Pin Label="恆逸資訊教育訓練中心"
                     Address="台北市松山區復興北路99號12樓,14樓,16樓"
                     Type="Place">
                   <maps:Pin.Position>
                       <maps:Position>
                           <x:Arguments>
                               <x:Double>25.052992</x:Double>
                               <x:Double>121.544633</x:Double>
                           </x:Arguments>
                       </maps:Position>
                   </maps:Pin.Position>
               </maps:Pin>
           </maps:Map.Pins>
       </maps:Map>
    </StackLayout>
    </ContentPage.Content>
    </ContentPage>
    
  • 3.2 也可在PinPage.xaml.cs加入Pin

    PinPage.xaml.cs

    public partial class PinPage : ContentPage
        {
            public PinPage()
            {
                        InitializeComponent();
                        Pin boardwalkPin = new Pin
                        {
                            Position = new Position(25.035473, 121.565297),
                            Label = "台北101",
                            Address = "台北市信義區信義路五段7號",
                            Type = PinType.Generic
                        };
                        boardwalkPin.MarkerClicked += OnMarkerClickedAsync;
            
                        map.Pins.Add(boardwalkPin);
             }
            async void OnMarkerClickedAsync(object sender, PinClickedEventArgs e)
             {
                    e.HideInfoWindow = true;
                    string pinName = ((Pin)sender).Label;
                    await DisplayAlert($"{pinName} 簡介", $"{pinName} 是高聳的地標性摩天大樓,設有商店、餐廳,以及位於 89 樓的觀景台。", "Ok");
              }
        }
            
  • 3.3 測試



主題4:透過Covid19Page內容頁,加入定位功能做為地圖的中心點,同時透過Data.gov取出公費COVID-19家用快篩試劑診所名單的CSV檔並將其資料產生Pin。


Xamarin.Essentials的Geolocation類別會提供 API 來擷取裝置的目前地理位置座標。

  • 4.1 存取地理位置功能,Android平台的特定設定

    需要粗略和精確位置的權限,並且必須在 Android 專案中設定。Android 10-Q (API 層級29或更高) 並要求 LocationAlways的權限。 開啟Android專案中 [Properties] 資料夾下的 AndroidManifest.xml 檔案,並在 [manifest] 節點內新增下列內容:

    AndroidManifest.xml

    
    <!--需要粗略和精確定位位置的權限-->
    <uses-feature android:name="android.hardware.location" android:required="false" />
    <uses-feature android:name="android.hardware.location.gps" android:required="false" />
    <uses-feature android:name="android.hardware.location.network" android:required="false" />
    <!--Android 10-Q (API 層級29或更高) 並要求 LocationAlways-->
    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
      
  • 4.2 存取定位功能,ios平台的特定設定

    開啟 plist 編輯器並新增 Privacy - Location When In Use Usage Description 屬性,並填寫一個值以向使用者顯示。
    <key>NSLocationWhenInUseUsageDescription</key>
    <string>Can we use your location when your application is being used?</string>

  • 4.3 加入手機定位功能,使用Xamarin.Essentials的Geolocation
    GetLastKnownLocationAsync()回傳經緯度

    Covid19Page.xaml.cs

      public partial class Covid19Page : ContentPage
        {
            public Covid19Page()
            {
                InitializeComponent();
             
                var geo = GetLastLocation().Result;
                Position center = new Position(geo.Item1,geo.Item2);
                MapSpan mapSpan = new MapSpan(center,0.05,0.05);
            }
       
            async Task<Tuple<double, double>> GetLastLocation()
            {
               var location = await Geolocation.GetLastKnownLocationAsync();
                if (location != null)
                {
                    return new Tuple<double, double>(location.Latitude, location.Longitude);
                }
                else {
                    return new Tuple<double, double>(25.035707, 121.564868);
                }
            }       
        }
    
  • 4.4 建立 Pin 資料來源的 NhiFst 類別

    建立DAL資料夾,加入NhiFst 類別。CSV 來源提供7個欄位(診所名稱、診所地址、診所電話、Long,Lat),在此只需提取其中五個欄位:(診所名稱、診所地址、診所電話、Long、Lat)

    NhiFst.cs

    using System;
    using System.Collections.Generic;
    using System.Text;
        
     namespace GoogleMaps.DAL
     {
     public class NhiFst
        {
                //診所名稱,診所地址,診所電話,Long,Lat
                public string Name { get; set; }
                public string Phone { get; set; }
                public double Lng { get; set; }
                public double Lat { get; set; }
           
                public NhiFst( string name, string address, string phone,double lng,double lat )        {
                    Name = name;    
                    Address = address;
                    Phone = phone;  
                    Lng = lng;
                    Lat = lat;  
                }
            }
        }
        
  • 4.5 使用HttpClients取出Data.gov的CSV檔
    加入NhiFstRepository類別,使用HttpClients取出CSV檔 https://quality.data.gov.tw/dq_download_csv.php?nid=150692&md5_url=38da966c8e5eda5b457a7366ce7f2c53

    NhiFstRepository.cs

    using System;
    using System.Collections.Generic;
    using System.Net.Http;
    using System.Text;
    using System.Threading.Tasks;
    using System.IO;
    using System.Net;
    using Newtonsoft.Json;
    using Xamarin.Forms;
    using System.Diagnostics;
    
    namespace GoogleMaps.DAL
    {
        public class NhiFstRepository
        {
            //公費COVID-19家用快篩試劑社區定點診所名單
            //縣市別,鄉鎮市區別,診所名稱,診所地址,診所電話,Long,Lat
            //https://data.gov.tw/dataset/150692
            //下載網址:https://quality.data.gov.tw/dq_download_csv.php?nid=150692&md5_url=38da966c8e5eda5b457a7366ce7f2c53
    
            const string Url = "https://quality.data.gov.tw/dq_download_csv.php?nid=150692&md5_url=38da966c8e5eda5b457a7366ce7f2c53";
    
            List<NhiFst> fstData=new List<NhiFst>();    
            public async Task<IEnumerable<NhiFst>> GetAll()
            {
                HttpClient client = new HttpClient();
                client.DefaultRequestHeaders.Add("Accept", "text/csv");
                var stream = await client.GetStreamAsync(Url).ConfigureAwait(false);
                using (var sr = new StreamReader(stream))
                {
                 string[] read;
                 char[] seperators = { ',' };
                 string data = sr.ReadLine();
                 Debug.WriteLine("DATA:" + data);  
                 while ((data = sr.ReadLine()) != null)
                {
                 read = data.Split(seperators, StringSplitOptions.RemoveEmptyEntries);
                 //縣市別[0],鄉鎮市區別[1],診所名稱[2],診所地址[3],診所電話[4],Long[5],Lat[6]
                 fstData.Add(new NhiFst(read[2], read[3], read[4], float.Parse(read[5]), float.Parse(read[6])));
                    }
                }
                return fstData;
            }
        }
    }
    
  • 4.6 建立Pin連繫所需的Location類別,對應至Pin類別

    Location.cs

    using System;
        using System.Collections.Generic;
        using System.ComponentModel;
        using System.Text;
        using Xamarin.Forms.Maps;
        
        namespace GoogleMaps.DAL
        {
            public class Location
            {
                Position _position;
                public string Address { get; }
                public string Description { get; }
                public Position Position { get; set; }
                public Location(string description,string address, Position position)
                {
                    Address = address;
                    Description = description;
                    Position = position;
                }
            }
        }
        
  • 4.7 建立ViewMode類別:PinItemsSourcePageViewModel,將CSV資料來源載入至Location

    PinItemsSourcePageViewModel.cs

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Diagnostics;
    using System.Text;
    using Xamarin.Essentials;
    using Xamarin.Forms.Maps;
        
        namespace GoogleMaps.DAL
        {
            public class PinItemsSourcePageViewModel
            {
                public PinItemsSourcePageViewModel()
                {
                    GetJsonData();    
                }
        
                NhiFstRepository manager = new NhiFstRepository();
                ObservableCollection<Location> _locations;
                public IEnumerable Locations => _locations;
                async void GetJsonData()
                {
                    _locations = new ObservableCollection<Location>()
                    {
                        new Location("Taipei101", "高聳的地標性摩天大樓,設有商店、餐廳,以及位於 89 樓的觀景台。", 
                        new Position(25.035940, 121.565148)),
                        new Location("恆逸資訊教育訓練中心", "台北市松山區復興北路99號12樓,14樓,16樓", 
                        new Position(25.052992, 121.544633))
                    };
                    var fstCollection = await manager.GetAll();
                    foreach (NhiFst d in fstCollection)
                    {
                        _locations.Add( new Location(d.Name,$"地址:{d.Address},電話:{d.Phone}",new Position(d.Lat,d.Lng)));
                    }
                }
            }
        }
        
  • 4.8 在Covid19Page內容頁加入Map及Pin控制項連繫至Location類別

    <?xml version="1.0" encoding="utf-8" ?>
    <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    x:Class="GoogleMaps.Covid19Page"
    xmlns:maps="clr-namespace:Xamarin.Forms.Maps;assembly=Xamarin.Forms.Maps"
    Title="快篩試劑地圖">
    <ContentPage.Content>
    <StackLayout>
    <maps:Map x:Name="map"
         ItemsSource="{Binding Locations}">
       <maps:Map.ItemTemplate>
           <DataTemplate>
               <maps:Pin Position="{Binding Position}"
                     Address="{Binding Address}"
                     Label="{Binding Description}" />
           </DataTemplate>
       </maps:Map.ItemTemplate>
    </maps:Map>
    </StackLayout>
    </ContentPage.Content>
    </ContentPage>
    
  • 4.9 在Covid19Page原始碼將BindingContext與ViewModel來源PinItemsSourcePageViewModel連繫,同時透過Map的MoveToRegion方法將Map中心點移至第3步驟提供的手機定位點

    Covid19Page.xaml.cs

    using GoogleMaps.DAL;
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Diagnostics;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using Xamarin.Essentials;
    using Xamarin.Forms;
    using Xamarin.Forms.Maps;
    using Xamarin.Forms.Xaml;
        
        
        namespace GoogleMaps
        {
            [XamlCompilation(XamlCompilationOptions.Compile)]
            public partial class Covid19Page : ContentPage
            {
        
                public Covid19Page()
                {
                    InitializeComponent();
                 
                    var geo = GetLastLocation().Result;
                    Position center = new Position(geo.Item1,geo.Item2);
                    MapSpan mapSpan = new MapSpan(center ,0.05,0.05);
        
                    BindingContext = new PinItemsSourcePageViewModel();
                    map.MoveToRegion(mapSpan);
                   
         
                }
           
                async Task<Tuple<double, double>> GetLastLocation()
                {
                   var location = await Geolocation.GetLastKnownLocationAsync();
                    if (location != null)
                    {
                        return new Tuple<double, double>(location.Latitude, location.Longitude);
                    }
                    else {
                        return new Tuple<double, double>(25.035707, 121.564868);
                    }
                }
               
               
            }
        }
        
  • 4.10 測試

完整程式碼

您可在下列課程中了解更多技巧喔!