文章目錄
- 1. 立即擷取當前位置
- 2. 持續跟蹤位置資訊
- 3. 在後台持續跟蹤
- 1.引入地圖控制項
- 2.設定製圖模式
- 3.設定顏色模式
- 4.指定新視角位置
- 5.定位我的位置並標記
- 6.擷取行車路線
Windows phone 8 已經不使用自家的bing地圖,新地圖控制項可以指定製圖模式、視圖等。bing地圖的定位誤差比較大,在模擬器中測試新地圖貌似比較理想。本節主要講解下位置服務以及新地圖控制項的使用。
快速導航:
一、定位服務
二、地圖和導航
一、定位服務
通過手機定位服務可以開發利用手機地理位置的應用。我們可以通過應用監視手機行蹤,配合地圖使用可以用於導航等。定位服務可以及時取得手機地理位置,也可以持續跟蹤手機移動,還可以在後台運行。
1. 立即擷取當前位置
我們可以通過一次操作擷取當前位置,下面的代碼示範了實現的方法。
[C#]
private async void OneShotLocation_Click(object sender, RoutedEventArgs e) { //地理位置訪問服務 Geolocator geolocator = new Geolocator(); //定義精度,米為單位 geolocator.DesiredAccuracyInMeters = 1; try { //開始擷取當前位置的經緯度 Geoposition geoposition = await geolocator.GetGeopositionAsync(); LatitudeTextBlock.Text = "經度:" + geoposition.Coordinate.Latitude.ToString("0.00"); LongitudeTextBlock.Text = "緯度:" + geoposition.Coordinate.Longitude.ToString("0.00"); } catch (Exception ex) { if ((uint)ex.HResult == 0x80004004) { StatusTextBlock.Text = "系統設定關閉了位置服務."; } } }
2. 持續跟蹤位置資訊
如果開啟持續跟蹤手機位置,當手機移動距離超出設定距離時,就會觸發位置改變事件,這個時候我們就可以通過環境資訊計算出手機的行動軌跡,速度方向等。下面示範了如何持續跟蹤。
[C#]
Geolocator geolocator = null;bool tracking = false;private void TrackLocation_Click(object sender, RoutedEventArgs e){ if (!tracking) { //地理位置訪問服務 geolocator = new Geolocator(); //精度層級 geolocator.DesiredAccuracy = PositionAccuracy.High; //超過多少米引發位置改變事件 geolocator.MovementThreshold = 100; //功能狀態改變時 geolocator.StatusChanged += geolocator_StatusChanged; //位置改變時 geolocator.PositionChanged += geolocator_PositionChanged; tracking = true; TrackLocationButton.Content = "停止跟蹤"; } else { geolocator.PositionChanged -= geolocator_PositionChanged; geolocator.StatusChanged -= geolocator_StatusChanged; geolocator = null; tracking = false; TrackLocationButton.Content = "跟蹤位置"; StatusTextBlock.Text = "停止"; }}void geolocator_StatusChanged(Geolocator sender, StatusChangedEventArgs args){ string status = ""; switch (args.Status) { case PositionStatus.Disabled: status = "位置服務設定被禁用"; break; case PositionStatus.Initializing: status = "正在初始化"; break; case PositionStatus.NoData: status = "無資料"; break; case PositionStatus.Ready: status = "已準備"; break; case PositionStatus.NotAvailable: status = "無法使用"; break; case PositionStatus.NotInitialized: break; } Dispatcher.BeginInvoke(() => { StatusTextBlock.Text = status; });}void geolocator_PositionChanged(Geolocator sender, PositionChangedEventArgs args){ Dispatcher.BeginInvoke(() => { LatitudeTextBlock.Text = "經度:" + args.Position.Coordinate.Latitude.ToString("0.00"); LongitudeTextBlock.Text = "緯度:" + args.Position.Coordinate.Longitude.ToString("0.00"); });}
3. 在後台持續跟蹤
位置跟蹤可以作為服務在後台運行,這個時候我們不需要更新UI,為了使我們的應用可以作為服務運行,我們需要右鍵開啟資訊清單檔,選擇用XML文字編輯器的方式,替換DefaultTask節點為如下資訊:
[XML]
<DefaultTask Name="_default" NavigationPage="MainPage.xaml"> <BackgroundExecution> <ExecutionType Name="LocationTracking" /> </BackgroundExecution> </DefaultTask>
然後我們需要註冊RunningInBackground事件,開啟App.xaml添加事件Application_RunningInBackground,代碼如下:
[XAML]
<!--處理應用程式的生存期事件所需的對象--> <shell:PhoneApplicationService Launching="Application_Launching" Closing="Application_Closing" Activated="Application_Activated" Deactivated="Application_Deactivated" RunningInBackground="Application_RunningInBackground"/>
在App.xaml.cs中添加靜態變數RunningInBackground和Geolocator,當Application_RunningInBackground事件時RunningInBackground為true,當Application_Activated事件時,RunningInBackground為false。代碼如下:
[C#]
//確定應用是否在後台運行public static bool RunningInBackground { get; set; }//提供對當前地理位置的訪問public static Geolocator Geolocator { get; set; }// 啟用應用程式(置於前台)時執行的代碼// 此代碼在初次開機應用程式時不執行private void Application_Activated(object sender, ActivatedEventArgs e){ RunningInBackground = false;}private void Application_RunningInBackground(object sender, RunningInBackgroundEventArgs args){ RunningInBackground = true;}
在mainpage中添加如下代碼:
[C#]
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e){ if (App.Geolocator == null) { App.Geolocator = new Geolocator(); App.Geolocator.DesiredAccuracy = PositionAccuracy.High; App.Geolocator.MovementThreshold = 100; App.Geolocator.PositionChanged += geolocator_PositionChanged; }}void geolocator_PositionChanged(Geolocator sender, PositionChangedEventArgs args){ if (!App.RunningInBackground) { Dispatcher.BeginInvoke(() => { LatitudeTextBlock.Text = "經度:" + args.Position.Coordinate.Latitude.ToString("0.00"); LongitudeTextBlock.Text = "緯度:" + args.Position.Coordinate.Longitude.ToString("0.00"); }); } else { Microsoft.Phone.Shell.ShellToast toast = new Microsoft.Phone.Shell.ShellToast(); toast.Content = args.Position.Coordinate.Latitude.ToString("0.00") + "," + args.Position.Coordinate.Longitude.ToString("0.00"); toast.Title = "位置:"; toast.NavigationUri = new Uri("/Page1.xaml", UriKind.Relative); toast.Show(); }}
二、地圖和導航
要用到新地圖控制項,需要先註冊,在phone:PhoneApplicationPage註冊標識。
[XAML]
xmlns:maps="clr-namespace:Microsoft.Phone.Maps.Controls;assembly=Microsoft.Phone.Maps"
1.引入地圖控制項
在XAML中添加如下代碼即可引入控制項。我們看到Center就是指當前地圖中心點的經緯度;ZoomLevel就是縮放層級; LandmarksEnabled 屬性設定為 true 以在 Map 控制項上顯示地標; PedestrianFeaturesEnabled 設定為 true,以顯示步行街構造。
[XAML]
<!--ContentPanel - 在此處放置其他內容--> <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <!--地圖控制項--> <maps:Map x:Name="MyMap" Center="30.5473, 114.2922" ZoomLevel="10" LandmarksEnabled="true" PedestrianFeaturesEnabled="true" /> <Button Foreground="Red" Content="指定位置" HorizontalAlignment="Left" Margin="295,530,0,0" VerticalAlignment="Top" Click="Button_Click_1" Width="151"/> <Button Foreground="Red" Content="製圖模式" HorizontalAlignment="Left" Margin="10,530,0,0" VerticalAlignment="Top" Click="Button_Click_2"/> <Button Foreground="Red" Content="顏色模式" HorizontalAlignment="Left" Margin="134,530,0,0" VerticalAlignment="Top" Click="Button_Click_3"/> <Button Foreground="Red" Content="我的位置" HorizontalAlignment="Left" Margin="10,602,0,0" VerticalAlignment="Top" Click="Button_Click_4"/> </Grid>
2.設定製圖模式
在製圖模式中有四個選項,分別如下:
Road:顯示正常的預設二維地圖。
Aerial:顯示航測圖。
Hybrid:顯示與道路和標籤重疊的地圖的“航測”視圖。
Terrain:為顯示的高地和水域構造(例如高山和河流)顯示自然地形映像。
下面看看如何切換。
[C#]
//切換製圖模式private void Button_Click_2(object sender, RoutedEventArgs e){ switch (MyMap.CartographicMode) { case MapCartographicMode.Aerial: MyMap.CartographicMode = MapCartographicMode.Hybrid; break; case MapCartographicMode.Hybrid: MyMap.CartographicMode = MapCartographicMode.Road; break; case MapCartographicMode.Road: MyMap.CartographicMode = MapCartographicMode.Terrain; break; case MapCartographicMode.Terrain: MyMap.CartographicMode = MapCartographicMode.Aerial; break; }}
3.設定顏色模式
顏色分為明和暗兩種,我們看看如何?。
[C#]
//切換顏色模式private void Button_Click_3(object sender, RoutedEventArgs e){ if (MyMap.ColorMode == MapColorMode.Light) MyMap.ColorMode = MapColorMode.Dark; else MyMap.ColorMode = MapColorMode.Light;}
4.指定新視角位置
我們可以通過編程方式切換視角位置到新的經緯度,並可以指定切換時的過渡效果,這裡指定的是拋物線的方式。
[C#]
private void Button_Click_1(object sender, RoutedEventArgs e){ //以拋物線的方式,把視角定位到光穀軟體園中心湖上空。 MyMap.SetView(new GeoCoordinate(30.476724, 114.406563), 16, MapAnimationKind.Parabolic);}
5.定位我的位置並標記
把地圖定位到我的當前位置。這個時候就需要藉助定位的功能,通過定位功能擷取到的經緯度執行個體類型不一樣,需要預先做一個轉換。轉換類CoordinateConverter如下。
[C#]
public static class CoordinateConverter{ /// <summary> /// 把定位位置轉換為地圖位置 /// </summary> /// <param name="geocoordinate"></param> /// <returns></returns> public static GeoCoordinate ConvertGeocoordinate(Geocoordinate geocoordinate) { return new GeoCoordinate ( geocoordinate.Latitude, geocoordinate.Longitude, geocoordinate.Altitude ?? Double.NaN, geocoordinate.Accuracy, geocoordinate.AltitudeAccuracy ?? Double.NaN, geocoordinate.Speed ?? Double.NaN, geocoordinate.Heading ?? Double.NaN ); }}
然後,我們需要在地圖上畫一個小正方形標記我的當前位置,並把地圖定位到這裡。
[C#]
//添加其他控制項到地圖,標識我的當前位置private async void Button_Click_4(object sender, RoutedEventArgs e){ //擷取我的地理位置 Geolocator myGeolocator = new Geolocator(); //精度 myGeolocator.DesiredAccuracyInMeters = 1; Geoposition myGeoposition = await myGeolocator.GetGeopositionAsync(); Geocoordinate myGeocoordinate = myGeoposition.Coordinate; //轉換經緯度GeoCoordinate GeoCoordinate myGeoCoordinate = CoordinateConverter.ConvertGeocoordinate(myGeocoordinate); //MessageBox.Show(myGeoCoordinate.ToString()); //定位地圖到我的位置 MyMap.SetView(myGeoCoordinate, 16, MapAnimationKind.Parabolic); //畫一個正方形,然後渲染在地圖的我的當前位置上 Rectangle MyRectangle = new Rectangle(); MyRectangle.Fill = new SolidColorBrush(Colors.Black); MyRectangle.Height = 20; MyRectangle.Width = 20; MapOverlay MyOverlay = new MapOverlay(); MyOverlay.Content = MyRectangle; MyOverlay.GeoCoordinate = myGeoCoordinate; MyOverlay.PositionOrigin = new Point(0, 0.5); MapLayer MyLayer = new MapLayer(); MyLayer.Add(MyOverlay); MyMap.Layers.Add(MyLayer);}
6.擷取行車路線
我們還可以通過定位和地圖實現導航的功能,下面示範了,從我的當前位置(光穀軟體園)到指定的位置(光穀創業街)如何行車。
[XAML]
<phone:PhoneApplicationPage.Resources> <DataTemplate x:Key="RouteListTemplate"> <TextBlock Text="{Binding}" FontSize="{StaticResource PhoneFontSizeMedium}" Margin="5,5,0,0"/> </DataTemplate> </phone:PhoneApplicationPage.Resources> <!--LayoutRoot 是包含所有頁面內容的根網格--> <Grid x:Name="LayoutRoot" Background="Transparent"> <Grid.RowDefinitions> <RowDefinition Height="auto"/> <RowDefinition Height="*"/> <RowDefinition Height="auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <TextBlock Text="地圖導航" Grid.Row="0" FontSize="{StaticResource PhoneFontSizeLarge}" Margin="0,0,0,20"/> <maps:Map x:Name="MyMap" Grid.Row="1" Center="30.476724, 114.406563" ZoomLevel="13"/> <TextBlock Text="駕車路線" Grid.Row="2" FontSize="{StaticResource PhoneFontSizeLarge}" Margin="0,10,0,20"/> <phone:LongListSelector x:Name="RouteLLS" Grid.Row="3" Background="Transparent" ItemTemplate="{StaticResource RouteListTemplate}" LayoutMode="List" IsGroupingEnabled="False"/> </Grid>
[C#]
public partial class Page1 : PhoneApplicationPage { public Page1() { InitializeComponent(); this.GetCoordinates(); } RouteQuery MyQuery = null; GeocodeQuery Mygeocodequery = null; List<GeoCoordinate> MyCoordinates = new List<GeoCoordinate>(); private async void GetCoordinates() { Geolocator MyGeolocator = new Geolocator(); MyGeolocator.DesiredAccuracyInMeters = 5; Geoposition MyGeoPosition = null; try { MyGeoPosition = await MyGeolocator.GetGeopositionAsync(TimeSpan.FromMinutes(1), TimeSpan.FromSeconds(10)); } catch (UnauthorizedAccessException) { MessageBox.Show("系統設定已關閉位置服務。"); } catch (Exception ex) { } MyCoordinates.Add(new GeoCoordinate(MyGeoPosition.Coordinate.Latitude, MyGeoPosition.Coordinate.Longitude)); Mygeocodequery = new GeocodeQuery(); Mygeocodequery.SearchTerm = "光穀創業街"; Mygeocodequery.GeoCoordinate = new GeoCoordinate(MyGeoPosition.Coordinate.Latitude, MyGeoPosition.Coordinate.Longitude); Mygeocodequery.QueryCompleted += Mygeocodequery_QueryCompleted; Mygeocodequery.QueryAsync(); } void Mygeocodequery_QueryCompleted(object sender, QueryCompletedEventArgs<IList<MapLocation>> e) { if (e.Error == null) { MyQuery = new RouteQuery(); MyCoordinates.Add(e.Result[0].GeoCoordinate); MyQuery.Waypoints = MyCoordinates; MyQuery.QueryCompleted += MyQuery_QueryCompleted; MyQuery.QueryAsync(); Mygeocodequery.Dispose(); } } void MyQuery_QueryCompleted(object sender, QueryCompletedEventArgs<Route> e) { if (e.Error == null) { //擷取具體的行程路線 Route MyRoute = e.Result; MapRoute MyMapRoute = new MapRoute(MyRoute); MyMap.AddRoute(MyMapRoute); List<string> RouteList = new List<string>(); foreach (RouteLeg leg in MyRoute.Legs) { foreach (RouteManeuver maneuver in leg.Maneuvers) { RouteList.Add(maneuver.InstructionText); } } RouteLLS.ItemsSource = RouteList; MyQuery.Dispose(); } } }
作者:[Lipan]
出處:[http://www.cnblogs.com/lipan/]
著作權聲明:本文的著作權歸作者與部落格園共有。轉載時須註明原文出處以及作者,並保留原文指向型連結,不得更改原文內容。否則作者將保留追究其法律責任。 《上一篇:Windows phone 8 學習筆記 裝置
系列目錄
下一篇:Windows phone 8 學習筆記 整合》