Windows phone 8 學習筆記(8) 定位地圖導航

來源:互聯網
上載者:User

標籤:des   blog   http   color   使用   os   strong   io   

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();            }        }    }
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.