一百行代码写一个WP8路线跟踪应用 已翻译 100%

hellowalker 投递于 2013/01/16 11:01 (共 14 段, 翻译完成于 01-21)
阅读 5655
收藏 63
6
加载中

目录

  • 介绍
  • 应用程序界面
  • 定时执行
  • 定位追踪
  • 设置地图Pitch和Heading属性
  • 后台位置追踪
  • Live Tile
  • 总结

介绍

我从Windows Phone7 还在测试阶段的时候就开始开发了,所以在Windows Phone 8 SDK开放后第一时间下载了。为了有趣,我决定创建一个简单的跑步定位追踪的应用来展示大量的特性,并且我将挑战在100行代码内完成此功能(不使用紧凑和可读性差的代码)

dodola
dodola
翻译于 2013/01/16 22:15
2
本文将通过我所开发的这个应用引导你深入探究  Windows Phone 8 中的以下特性:
  • 新增的地图控件(拥有步行与三维路标功能)。
  • 如何跟踪用户的位置,包括当其他程序运行时在后台跟踪的情况。
  • 在地图上添加线条注释
  • 一些3D地图的特性,设置 pitch 与 heading 属性。
  • 使用新增的模板创建动态Tile

虽然使用Windows Phone 7 开发一个这样的路线跟踪应用也是完全可以(商城里已经有很多很棒的例子了),不过Windows Phone 8 中新增的特性与功能可以让它的功能更加丰富。

注意哦: 我最初将本文发表在诺基亚开发者百科(Nokia Developer Wiki)上,不过在CodeProject 上我也分享了,在那里你可以找到我写的其他一些文章

greyCode
greyCode
翻译于 2013/01/17 20:38
2

应用程序界面

这个程序的UI十分简单,主要由一张全屏的地图组成,地图上面显示跑步的统计信息,正如下面的截图所示:

程序界面的XAML代码如下:

<Grid util:GridUtils.RowDefinitions="Auto, *">

  <!-- title -->
  <StackPanel Grid.Row="0" Margin="12,17,0,28">
    <StackPanel Orientation="Horizontal">
      <Image Source="/Assets/ApplicationIconLarge.png" Height="50"/>
      <TextBlock Text="WP8Runner" VerticalAlignment="Center"
                  Margin="10 0 0 0"
                  FontSize="{StaticResource PhoneFontSizeLarge}"/>
    </StackPanel>
  </StackPanel>

  <!--ContentPanel - place additional content here-->
  <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">

    <!-- the map -->
    <maps:Map x:Name="Map"
          ZoomLevel="16"/>

    <!-- 步行统计 -->
    <Grid Background="#99000000" Margin="20" 
          VerticalAlignment="Bottom">
      <Grid Margin="20"
            util:GridUtils.RowDefinitions="40, 40, Auto"
            util:GridUtils.ColumnDefinitions="*, *, *, *">
          
        <!-- 距离 -->
        <TextBlock Text="Distance:"/>
        <TextBlock Text="0 km" Grid.Column="1" x:Name="distanceLabel"
              HorizontalAlignment="Center"/>

        <!-- 时间 -->
        <TextBlock Text="Time:" Grid.Column="2"/>
        <TextBlock Text="00:00:00" Grid.Column="3" x:Name="timeLabel"
              HorizontalAlignment="Center"/>

        <!-- 卡路里 -->
        <TextBlock Text="Calories:" Grid.Row="1"/>
        <TextBlock Text="0" Grid.Column="1" x:Name="caloriesLabel"
              HorizontalAlignment="Center" Grid.Row="1"/>

        <!-- 步幅 -->
        <TextBlock Text="Pace:" Grid.Column="2" Grid.Row="1"/>
        <TextBlock Text="00:00" Grid.Column="3" x:Name="paceLabel"
              HorizontalAlignment="Center" Grid.Row="1"/>

        <Button Content="Start"
                Grid.Row="2" Grid.ColumnSpan="4"
                Click="StartButton_Click"
                x:Name="StartButton"/>
      </Grid>
    </Grid>
  </Grid>
</Grid>
greyCode
greyCode
翻译于 2013/01/18 09:51
2
GridUtilsis 是我几年前写的一个工具类,可方便定义网格(Grid)的行列属性(该类适用于 WPF,Silverlight 以及Windows Phone)。如果你依序从头编写这个应用,为了能使用地图,就得加入下面的命名空间定义:
xmlns:maps="clr-namespace:Microsoft.Phone.Maps.Controls;assembly=Microsoft.Phone.Maps" 

在构建与运行程序之前,你得先开启地图功能。打开 '''WPAppManifest.xml''',找到 Capabilities 标签然后选中 ID_CAP_MAP,这时ID_CAP_LOCATION也(自动)被选中:

Capabilites 用于决定你的应用中打算加入的手机功能,从而方便用户了解这个应用能做些什么。

选中以上功能后,构建运行程序你就可以看到如上所述的界面。

greyCode
greyCode
翻译于 2013/01/18 10:38
1

地图控件的其中一项改进即它是完全基于矢量的(Windows Phone 7中的地图是基于位图),这便使得地图在缩放时的过渡更加平滑,而且还可以进行3D变换(稍后将会看到)。对我们的路线跟踪应用而言,地图控件还有其他一些有用的功能,如步行与路标。 可以通过如下的代码设置:

<!-- the map -->
<maps:Map x:Name="Map"
      PedestrianFeaturesEnabled="True"
      LandmarksEnabled="True"
      ZoomLevel="16"/>

经过以上设置,地图将会显示一些有用的东西,比如街道、路标等信息:

(顺便插一句,我可没想把这50行XAML算到我的代码总行数里哈 :-P)

Windows Phone 8中的地图还有很多新特性我没在这个程序里用到。比如你可以用下新的ColorMode属性,它能让你渲染一幅‘暗色模式’的地图以便在低光环境下查看,甚至可以让这个路线跟踪应用根据当天的时间自动选择ColorMode

greyCode
greyCode
翻译于 2013/01/18 13:54
1

定时执行

当"Start"按钮按下后程序就开始的GPS接收器就开始追踪用户的位置来标注用户的行动轨迹,如果有兴趣的话还可以计算已经跑步的时间和统计各种数据,我们先从两项功能中简单的一项开始,定时执行.当我们点击开始按钮后 DispatcherTimer就开始执行了并且记录下按钮按下的时间,另一个timer定时器来更新显示已经执行了多长时间.

public partial class MainPage : PhoneApplicationPage
{
  private DispatcherTimer _timer = new DispatcherTimer();
  private long _startTime;

  public MainPage()
  {
    InitializeComponent();

    _timer.Interval = TimeSpan.FromSeconds(1);
    _timer.Tick += Timer_Tick;
  }

  private void Timer_Tick(object sender, EventArgs e)
  {
    TimeSpan runTime = TimeSpan.FromMilliseconds(System.Environment.TickCount - _startTime);
    timeLabel.Text = runTime.ToString(@"hh\:mm\:ss");
  }

  private void StartButton_Click(object sender, RoutedEventArgs e)
  {
    if (_timer.IsEnabled)
    {
      _timer.Stop();
      StartButton.Content = "Start";
    }
    else
    {
      _timer.Start();
      _startTime = System.Environment.TickCount;
      StartButton.Content = "Stop";
    }
  }
}
以上代码完成后,点击"start"按钮后定时器就开始执行了
dodola
dodola
翻译于 2013/01/19 09:42
1

位置追踪

下一步需要做的就是在计时器运行的同时来记录位置信息。Window Phone的API 库有GeoCoordinateWatcherclass 类, 其中的一个方法 PositionChangedevent 可以用来记录用户的位置和路径。 而后用MapPolyLine方法可以很简单地在地图上用地理坐标来渲染出用户的路径。每一次这个事件被激活,就会在地图上增加一个点,具体代码如下:

public partial class MainPage : PhoneApplicationPage
{
  private GeoCoordinateWatcher _watcher = new GeoCoordinateWatcher(GeoPositionAccuracy.High);
  private MapPolyline _line;
  private DispatcherTimer _timer = new DispatcherTimer();
  private long _startTime;

  public MainPage()
  {
    InitializeComponent();

    //初始化一个line类用来记录路径
    _line = new MapPolyline();
    _line.StrokeColor = Colors.Red;
    _line.StrokeThickness = 5;
    Map.MapElements.Add(_line);

    _watcher.PositionChanged += Watcher_PositionChanged;

    //..计时器代码在此处省略..
  }

  //.. 计时器代码此处被省略 ...

  private void StartButton_Click(object sender, RoutedEventArgs e)
  {
    if (_timer.IsEnabled)
    {
      _watcher.Stop();
      _timer.Stop();
      StartButton.Content = "Start";
    }
    else
    {
      _watcher.Start();
      _timer.Start();
      _startTime = System.Environment.TickCount;
      StartButton.Content = "Stop";
    }
  }


  private void Watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
  {
    var coord = new GeoCoordinate(e.Position.Location.Latitude, e.Position.Location.Longitude);

    Map.Center = coord;
    _line.Path.Add(coord);
  }
}

上面的代码可以就可以实现把用户的路径层加到地图上,如下图所示。

sjZ52
sjZ52
翻译于 2013/01/18 11:09
1

PositionChanged 事件可以进一步的扩展成计算总运行距离,卡路里消耗和速度.使用GeoCoordinate.GetDistanceTo可以用来计算两个地点之间的距离:

private double _kilometres;
private long _previousPositionChangeTick;

private void Watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
{
  var coord = new GeoCoordinate(e.Position.Location.Latitude, e.Position.Location.Longitude);

  if (_line.Path.Count > 0)
  {
    // find the previos point and measure the distance travelled
    var previousPoint = _line.Path.Last();
    var distance = coord.GetDistanceTo(previousPoint);

    // compute pace
    var millisPerKilometer = (1000.0 / distance) * (System.Environment.TickCount - _previousPositionChangeTick);

    // compute total distance travelled
    _kilometres += distance / 1000.0;

    paceLabel.Text = TimeSpan.FromMilliseconds(millisPerKilometer).ToString(@"mm\:ss");
    distanceLabel.Text = string.Format("{0:f2} km", _kilometres);
    caloriesLabel.Text = string.Format("{0:f0}", _kilometres * 65);
  }
  

  Map.Center = coord;
  
  _line.Path.Add(coord);
  _previousPositionChangeTick = System.Environment.TickCount;
}
Runner's不去测量每小时的速度是多少英里或公里.相反,速度用来计算一段跑完距离里所需的时间.这种计算方法可以更轻松的确定你整体的跑步时间,例如:如果你跑步的速度是四分钟一公里,那么你会在20分钟后跑完五公里.
dodola
dodola
翻译于 2013/01/18 15:39
1

注意:上面的代码使用了一个非常简单的卡路里消耗算法,假设每跑一公里消耗65卡路里,一个更精确的算法会根据跑步者的体重和速度和其他环境因素来进行计算,将这个功能作为一个小练习留给读者.

对于开发应用程序,模拟器有一些包括跟踪用户的位置在内的非常有用的特性。你可以沿着路线记录一些点,然后每隔一段时间重复一下,你也可以将这些模拟数据保存成一个xml,以便以后重复执行.

这可能需要一定时间来创建一个真实的数据来模拟真实的运行情况,但是你至少有一次来做这件事.

dodola
dodola
翻译于 2013/01/19 09:55
1

设置地图视角和指向

由于 Windows Phone8 地图的向量性质,它可以使用视角和指向属性转换视图。 视角属性设置地图的观察角度,提供了一个透视的图像,而非一个自上而下的图像,而指向属性则使你可以旋转地图。 多数卫星导航系统将这些特效组合起来呈现地图,这样它看起来就像直接在你的面前一样。很多人觉得这样的地图比较容易理解(他们不需要在大脑里旋转地图)。

你可以很容易的将这些功能添加到你的应用中,首先,在 XAML 中设置地图视角:

<!-- the map -->
<maps:Map x:Name="Map"
      PedestrianFeaturesEnabled="True"
      LandmarksEnabled="True"
      Pitch="55"
      ZoomLevel="18"/> 
K6F
K6F
翻译于 2013/01/21 13:27
1
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
加载中

评论(12)

lonno1
lonno1
开源才是王道!
SamH
SamH

引用来自“leixu_txtek”的评论

引用来自“SamH”的评论

学习了……

黄山 认识我吗?

好吧,我认出了txtek……
leixu2
leixu2

引用来自“SamH”的评论

学习了……

黄山 认识我吗?
unnamed
unnamed

引用来自“Ghost_”的评论

引用来自“棟梁”的评论

是否 Windows Phone 8 比較 Android 强大?

不是
Serysew
Serysew
目测一下WP8能否逆袭? WP7很令人失望
棟梁
多謝 Ghost 的回复
iiiiiiiii
iiiiiiiii

引用来自“棟梁”的评论

是否 Windows Phone 8 比較 Android 强大?

棟梁
是否 Windows Phone 8 比較 Android 强大?
dadait
dadait
马克。
m
missyang
很轻大
返回顶部
顶部