Karten-Apps für Windows Phone 8 im Handumdrehen – Teil 2
In Teil 1 meines Karten-App Tutorials habe ich dargestellt, wie man eine Karte anzeigt und welche Einstellungen möglich sind. Im aktuellen Blogbeitrag möchte ich Euch einige weitere Features zeigen, die im Microsoft.Phone.Map Framework vorhanden sind. Auf zwei dieser Features möchte ich nun näher eingehen. Es geht einerseits um die Berechnung der Entfernung zwischen zwei Positionen und andereseits um die Ermittlung der aktuellen GPS-Position des Handys. Das Framework stellt dem Mobile App Entwickler fertig Methoden dafür bereit, somit ist die Implementierung in wenigen Zeilen Code realisiert:
1. Entfernungsmessung zwischen zwei Positionen
XAML-seitig erweitern wir das MAP Control um einen EventHandler:
[code language=“xml“]
<maps:Map x:Name=“WorldMap“
Center=“50.09, 8.77″
ZoomLevel=“13″
CartographicMode=“Terrain“
Pitch=“50″
Tap=“WorldMap_Tap“>
<mapstk:MapExtensions.Children>
<mapstk:Pushpin x:Name=“MarktplatzMarker“
GeoCoordinate=“50.106, 8.763″
Content=“Marktplatz“/>
</mapstk:MapExtensions.Children>
</maps:Map>
[/code]
Im Eventhandler wird mit Hilfe der Methode GetDistance() die Enternung berechnet. Anschließend wird eine Linie zwischen den beiden Geopositionen gezeichnet
[code language=“csharp“]
private void WorldMap_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
// Entfernung zwischen Marktplatz und Endposition berechnen
Pushpin marktplatz = this.FindName(„MarktplatzMarker“) as Pushpin;
GeoCoordinate startLocation = marktplatz.GeoCoordinate;
GeoCoordinate endLocation = this.WorldMap2.ConvertViewportPointToGeoCoordinate(e.GetPosition(sender as UIElement));
double distanceFromMarktplatz = endLocation.GetDistanceTo(startLocation);
// Entfernung im Pushpin anzeigen
marktplatz.Content = string.Format(new CultureInfo(„de-DE“), „Marktplatz\n{0:F1} km“, distanceFromMarktplatz / 1000);
// Zeichne Entfernungslinie
MapPolyline distanceLine = new MapPolyline();
distanceLine.StrokeColor = Colors.Blue;
distanceLine.StrokeThickness = 3;
distanceLine.Path.Add(startLocation);
distanceLine.Path.Add(endLocation);
this.WorldMap.MapElements.Clear();
this.WorldMap.MapElements.Add(distanceLine);
}
[/code]
2. Ermitteln und Darstellen der eigenen Position
Zur Nutzung der GPS-Funktionalität des Phones ist die Freigabe der ID_CAP_LOCATION in der WMAppManifest.xml Datei erforderlich. XAML-seitig ergänzen wir die MapExtensions um das UserLocationMarker Control und fügen ausserhalb des Map Control eine Schaltfläche zur Aktivierung der Positionsbestimmung hinzu:
[code language=“csharp“]
<mapstk:MapExtensions.Children>
<mapstk:Pushpin x:Name=“MarktplatzMarker“ GeoCoordinate=“50.106, 8.763″ Content=“Marktplatz“/>
<mapstk:UserLocationMarker x:Name=“UserLocationMarker“ Visibility=“Collapsed“/>
</mapstk:MapExtensions.Children>
</maps:Map>
<Button Content=“Show current position“ VerticalAlignment=“Bottom“ Background=“Gray“ Click=“Button_Click“/>
</Grid>
[/code]
Im Codebehind benötigen wir neben dem Eventhandler noch zwei weitere Methoden und das war´s:
[code language=“csharp“]
private void Button_Click(object sender, RoutedEventArgs e)
{
GetUserPosition();
}
private async void GetUserPosition()
{
try
{
this.UserLocationMarker = this.FindName(„UserLocationMarker“) as UserLocationMarker;
this.UserLocationMarker.GeoCoordinate = await GetCurrentLocation();
// den Marker für die aktuelle Position einschalten und Kartenausschnitt darauf zentrieren
this.UserLocationMarker.Visibility = System.Windows.Visibility.Visible;
this.WorldMap.SetView(this.UserLocationMarker.GeoCoordinate, 15);
}
catch (Exception ex)
{
if ((uint)ex.HResult == 0x80004004)
{
// im Falle, dass die Ortung ausgeschaltet ist, wird eine Exception geworfen
MessageBox.Show(„Bitte Ortung einschalten unter Einstellungen“);
}
else
{
// etwas anderes ist passiert
}
}
}
private async Task<GeoCoordinate> GetCurrentLocation()
{
Geoposition currentPosition;
Geolocator locator = new Geolocator();
currentPosition = await locator.GetGeopositionAsync();
return new GeoCoordinate(currentPosition.Coordinate.Latitude, currentPosition.Coordinate.Longitude)
}
[/code]
Zur Laufzeit kann der Aufruf der asynchronen Methode locator.GetGeopositionAsync() 2 – 3 Sekunden dauern. Aus Usability Sicht müsste hier ein Waiting Cursor eingeblendet werden. Eine nette Animation hin zur angebenen Position ermöglicht die Methode this.WorldMap.SetView(). Ich habe für den ZoomLevel Parameter einen größeren als den initial (in XAML) definierten Wert angegeben. So entsteht eine kurze Kamerafahrt mit einem coolen Eintaucheffekt. Have fun!