Windows phone 8 学习笔记(8) 定位地图导航

Windows phone 8 学习笔记(8) 定位地图导航

Posted on 2013-06-08 09:10 lipan 阅读( 626) 评论( 0) 编辑 收藏

 Windows phone 8 已经不使用自家的bing地图,新地图控件可以指定制图模式、视图等。bing地图的定位误差比较大,在模拟器中测试新地图貌似比较理想。本节主要讲解下位置服务以及新地图控件的使用。

快速导航:
    一、定位服务
    二、地图和导航

一、定位服务

通过手机定位服务可以开发利用手机地理位置的应用。我们可以通过应用监视手机行踪,配合地图使用可以用于导航等。定位服务可以及时取得手机地理位置,也可以持续跟踪手机移动,还可以在后台运行。

1. 立即获取当前位置

我们可以通过一次操作获取当前位置,下面的代码演示了实现的方法。

[C#]
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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#]
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
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]
?
1
2
3
4
5
< DefaultTask Name = "_default" NavigationPage = "MainPage.xaml" >
   < BackgroundExecution >
     < ExecutionType  Name = "LocationTracking" />
   </ BackgroundExecution >
</ DefaultTask >

然后我们需要注册RunningInBackground事件,打开App.xaml添加事件Application_RunningInBackground,代码如下:

[XAML]
?
1
2
3
4
5
<!--处理应用程序的生存期事件所需的对象-->
< 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#]
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//确定应用是否在后台运行
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#]
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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]
?
1
xmlns:maps="clr-namespace:Microsoft.Phone.Maps.Controls;assembly=Microsoft.Phone.Maps"

1.引入地图控件

在XAML中添加如下代码即可引入控件。我们看到Center就是指当前地图中心点的经纬度;ZoomLevel就是缩放级别; LandmarksEnabled 属性设置为 true 以在 Map 控件上显示地标; PedestrianFeaturesEnabled 设置为 true,以显示步行街构造。

[XAML]
?
1
2
3
4
5
6
7
8
9
<!--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#]
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//切换制图模式
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#]
?
1
2
3
4
5
6
7
//切换颜色模式
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#]
?
1
2
3
4
5
private void Button_Click_1( object sender, RoutedEventArgs e)
{
     //以抛物线的方式,把视角定位到光谷软件园中心湖上空。
     MyMap.SetView( new GeoCoordinate(30.476724, 114.406563), 16, MapAnimationKind.Parabolic);
}

 

5.定位我的位置并标记

把地图定位到我的当前位置。这个时候就需要借助定位的功能,通过定位功能获取到的经纬度实例类型不一样,需要预先做一个转换。转换类CoordinateConverter如下。

[C#]
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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#]
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
//添加其他控件到地图,标识我的当前位置
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]
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
< 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#]
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
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/]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值