Tally

    你是不是在需要计数的时候,感到手指不够用?也许你正需要记录你朋友游了几圈,或者是举重了几次。也许你需要记录很长一段事件内,某件事发生了几次。比如,过去我没法统计我的妻子问过我多少次“我是不是看起来胖了?”,现在,有了Tally,我就可以进行统计了。

    在这一章中,我们将编写一个名为Tally的应用。每当你点击一次屏幕,计数器都会加一。同时,还有一个reset按钮,用于清空计数器。它会一直保持计数,除非你按下reset按钮,或者卸载掉它。

    不管这个应用销售情况如何,我必须承认Tally不是一个吸引人的应用。尽管如此,它足够简单,可以很好地介绍Windows Phone的开发。相较于其他章,本章不太关注应用本身,而更关注在Visual Studio中创建的Windows Phone项目的结构和基本特性。

question

为什么Windows Phone的应用看起来都这么简单?
    这是基于艺术的选择。Windows Phone及其应用都被设计来简单明了地表达信息。就好像是机场,车站里面的标志。微软称这种风格为Metro。标准的Metro风格偏好大块地留白,使用简单的单色图标来突出信息。
    不同于iPhone,iPhone强调的是明亮,有立体感的视觉效果。iPhone鼓励模拟真实世界的视觉效果(比如记事本应用看起来就像是一个真实的纸质记事本的效果),而Windows Phone则不鼓励刻意地模仿真实世界的视觉效果。相反,除了游戏和一些新奇的应用以外,Windows Phone要求应用看上去更“数字化”。

question

为什么大多数WP7应用都使用的是黑底白字?
    这同样也是基于艺术的选择。黑色不仅更加时尚,同时也有现实的意义。不少Windows Phone使用了OLED的屏幕。这种屏幕可以有效地利用电池(不需要背光源),电池使用时间依赖于屏幕的颜色和亮度。所以在这种屏幕下,黑底白字比白底黑字更省电。

light     更多关于Metre的信息,访问http://go.microsoft.com/fwlink/?LinkID=190696

分解一个“Windows Phone Application”的项目

    当你在Visual Studio中建立一个新的“Windows Phone Application”项目时,你已经得到了一个完整的应用。它可以直接编译到.xap文件中,或者发布到模拟器/手机上。当然它除了显示一点文字外,什么都不会做。不过,其中已经包含了很多基础结构。在开始编写Tally应用前,我们先理解下,一个新的“Windows Phone Application”的各个组成部分。

light     Visual Studio根据主屏幕上显示控件的不同,提供了一些更复杂的应用模板:databound (list) application,panorama application,和pivot application。基本上本书所有的应用都是基于最基础的“Windows Phone Application”创建的,在上面添加一个databound list,panorama或者pivot控件都是很简单的。

关于.xap
    .xap是由Silverlight引入,在XNA应用也同样得到使用。它仅仅是一个.zip文件。如果你把后缀名改成.zip的话,你就可以像.zip文件一样查看里面的内容。一个.xap文件里面包含了一些文件:编译过后的DLL,清单,图片,可能还有其它一些没有编译进DLL的资源文件。

dot

应用的清单

    WMAppManifest.xml(其中WM部分来至于已经out了的“Windows Mobile”术语)是应用的清单。它向操作系统描述了应用的相关信息:名字,外表,如何开始,允许的功能等等。下面就是VS产生的命名为“Tally”的新项目中的对应文件,位于Properties文件夹中。

WMAppManifest.xml

    这个应用的清单是个奇怪的文件,因为在Marketplace审核过程中,大多数设置都会被修改。因此,由Marketplace下载到的版本和你本机的版本将会不一样。

    App的元素包括了:ProductID,是一个唯一标识你的应用的GUID;RuntimeType,指出了这是一个Silverlight应用还是XNA应用;Title,用于显示你安装的应用(在app list中或者在Games hub中);剩下的4个属性只是用来在Marketplace中列出你的应用。但是这些值(包括Title)在你提交应用的时候,都会被重写。

    Genre影响到你的应用的安装位置。如果是apps.normal则会放置到普通的app list中,如果是apps.games则会放置到Games hub中(Silverlight应用也可以放置到Games hub中)。一个应用只能被安装到其中一个位置。一般开发的时候设置成apps.normal会比较方便,应为模拟器中没有包含Games hub。当你将应用提交到Marketplace的时候,这个值也会根据你在网页上的选择进行重写。

    IconPath是关于图标的设置。Tasks是指出你的应用从哪个Silverlight页面开始运行。Tokens中则是关于Tile的信息(当用户把你的应用放在他们手机的首页上的时候就会显示相关信息)。

另一个清单
    Visual Studio项目中包含了第二个清单文件AppManifest.xml,同样也在Properties文件夹中。这个是Silverlight的基础结构需要的,你接触不到这个文件。

dot


功能(Capabilities)

    WMAppManifest.xml中最有趣的部分就是关于功能(Capabilities)。其中包含了应用的行为许可,但是用户却不一定希望应用产生这些行为。比如涉及到隐私(用户的位置信息),或者可能产生费用(拨号,发送短信)。Visual Studio中产生的清单包含了所有可用的功能。你可以尝试修改这个列表,看看你的应用的哪些行为会受到限制。不过这没有什么意义,Marketplace的验证程序会自动侦测你的应用需要哪些功能,然后重写一个最小的功能清单。

    在Marketplace中,当用户在考虑是否下载你的应用的时候,会被告知你的应用需要获取哪些功能许可。每个功能都有个简单易懂的名字,比如ID_CAP_LOCATION在Marketplace中是“location services”。用户在下载你的应用之前,必须进行这样的许可。这种定位服务就需要用户进行明确地许可。在下载这种应用前,Marketplace会提醒用户是否同意发送他们的位置信息。

light     一旦你的程序已经运行了起来,你就不需要判断是否获得了相应的功能许可(也没有相应的API)。因为,如果你的应用已经在运行了,就意味着它已经获得了所有相关功能许可。这些许可是不能被撤销的。

warning

ID_CAP_NETWORKING是唯一一个需要进行手动请求的功能
    一般而言
,除了这个功能以外 ,你都可以让Marketplace的验证程序来处理这个功能列表。Marketplace不能确定你的应用是否会用到手机的网络功能。如果ID_CAP_NETWORKING被列在了你的功能列表中,那么不管你是否会用到网络功能,你都会获得这个许可。反之亦然。

    用户不需要对所有功能都进行许可,你也不必操心是否某个功能得到了许可。只需要记住下面几点:
    如果你的应用已经在运行了,那么这就意味着你的应用已经获得了所有许可。
    如果你的应用已经从Marketplace上成功下载,功能清单里面就会包含所有你的应用需要的功能了。(除了上面提到的ID_CAP_NETWORKING)

light

    你需要注意限制应用所需要的功能,从而提高应用的竞争力。比如,如果你的小费计算器需要使用手机的数据连接,那么用户很可能就不会购买了。所以,如果你不需要使用网络,记得去掉ID_CAP_NETWORKING。
    你最好使用一下Windows Phone Capability Detection Tool(C:\Program Files\Microsoft SDKs\Windows Phone\v7.0\Tools\CapDetect 文件夹下)。它会和Marketplace一样对你的应用进行功能侦测。不过和Marketplace一样,对ID_CAP_NETWORKING的判断都不太准确。

question

为什么我修改来功能列表之后,我就不能在真机上调试我的应用了?
    这个和讨厌的ID_CAP_NETWORKING有关。没有了ID_CAP_NETWORKIN,调试器也不能和手机通讯了。所以开发的时候要保留它,等正式发布的时候再去掉它。

question

我要如何才能在自己的游戏中利用Xbox LIVE的特性?
    有些功能是只向移动运营商和手机制造商这种大神开放的,你我这种凡人都是用不了的。ID_CAP_GAMERSERVICES也是这种特殊功能之一。它可以使用Xbox LIVE API,但是只针对获得了微软许可的游戏。如果你想知道自己都错过了什么,你可以使用Visual Studio的Object Browser来查看Microsoft.Xna.Framework.GamerServices程序集,了解Xbox LIVE的功能。除非你注册成为了Xbox LIVE的开发者,或者通过某些特殊的途径使用上Xbox LIVE,否则其中的大多数功能都会抛出NotSupportedException的异常。


图片

    由Visual Studio创建的项目中已经包含了3张图片:
    ApplicationIcon.png-主图标,不管应用被安装到哪里,都会显示这个图标。如果是普通的应用(放在手机的app list中),图标应该是62x62像素以避免缩放。如果是游戏(放在Games hub中),图标应该是173x173像素。
    Backgroud.png-Tile图标(173x173),当用户将应用放置在手机的起始页面时显示。为什么一个图标的名字会叫Background呢,因为它是作为tile的背景。在程序清单中设置的标题会自动覆盖到tile的左下角,所以在设计这个图片的时候要为标题预留下空间。
    SplashScreenImage.jpg-闪屏图片(480x800)会在应用启动时显示。

    这些图片可以是JPEG或者PNG格式。你可以任意修改,同时记得要在你的程序清单中也进行对应的修改。

light

    如果你想设计一个符合Windows Phone内置程序风格的图标,它必须使用透明的背景,同时里面的图形应该是:
    ➔ 白色
    ➔ 简单的几何图形
    ➔ 如果可能的话,尝试重新组合Windows Phone已经使用过的图形
    ➔ 符合我们实际生活的比喻

    62x62大小的图标需要留出12像素的白边,换句话说,实际只有图片中央的38x38像素包含内容。173x173的图标则使用73x73的内容,偏上3个像素放置。上方留47像素的空白,下方留出53像素,左右各留50像素。

    当你想设计一个特别点的图片时,也许想要缩小留白的大小。一般情况下,Background.png应该和ApplicationIcon.png是一致的,只有大小上的区别。游戏的话,则不用依照上面的设计指导。

    设计这样一个图标需要耐心和练习。你可以使用像PAINT.NET这样的工具。同时Wingdings和Webdings字体也会对你的设计有所帮助。

    微软并没有给出严格的,或者官方的指导。大多数情况下,只要看上去不错就行了。

question

我要如何才能使用用户主题的背景色来作为图标的背景色,就和内置程序一样?
    每个tile图标都是放置在以用户主题的背景色作为背景的方块上面。所以你只需要保证你使用的是透明背景的PNG文件就可以了。但不幸的是,在app list中的时候,每个第三方的应用图标都是放置在黑色背景的方块上面的,所以在app list里面就没法达到内置程序一样的效果了。这种情况下,你可以使用一个有背景色的图标。

warning

Marketplace中的图标和你应用真正的图标有不一样的设计指导
    一般鼓励你设计Tile图标时使用透明背景。但是当你上传应用到Marketplace的时候,要避免使用透明背景的图标。在手机的Marketplace中,图标是放置在黑色背景的方块上面的。而在Zune中,默认情况下,图标都是放置在白色背景下。如果是一个标准的Windows Phone风格的图标的话,透明背景里面是白色的图形,就会完全看不见。
    所以,你必须选择一个有背景色的图标作为Marketplace中的图标。

warning

图标和闪屏图片需要将生成操作(Build Action)设置为内容(Content)
    当你对这3个图片进行替换时,要确保每个文件的Build Action都被设置为了Content而不是默认的Resources。这样,这些文件就会直接部署到.xap文件中,而不是编译进DLL中。
    Copy to Output Directory就不重要了,不管你选什么,最终都会复制到生成的.xap文件中。


MainPage.xaml

    每个应用都是由一个或多个页面构成的。一个新建的项目生成MainPage这个页面。这个页面定义了用户载入应用之后可以看见什么。由MainPage.xaml(包含了UI)和MainPage.xaml.cs(包含了业务逻辑)两部分组成。

warning

记得要在WMAppManifest.xml中引用MainPage.xaml
    如果你重命名了MainPage.xaml,记得要在WMAppManifest.xml中修改对应的引用。

MainPage.xaml

    简单的观察这个文件,我们可以得知:
    ➔ 这是一个名为MainPage的类(位于Tally命名空间下),派生于PhoneApplicationPage控件。
    ➔ 它只支持肖像(垂直)方向。
    ➔ 包含了两个文本块,分别代表应用的名称和页面的标题。
    ➔ 这个页面使用了Grid和StackPanel控件来进行页面布局。除开两个文本块,其余的内容都被放置在名为ContentGrid的grid中。
    ➔ 即使只是一个很简单的页面,也包含了许多信息。

    我们会进一步深入:
    ➔ 文件开始使用的XML命名空间。
    ➔ 通过类似{StaticResource XXX}的方式来调用手机主题相关的资源。

    方向是一个有趣同时也很重要的主题,在第三章中会加以讨论。这个页面也提供了关于如何使用应用工具条的方法(被注释在页面的最后),但是这章的Tally是少数几个不需要使用工具条的应用之一。下一章才会涉及到相关内容。

XML命名空间

    MainPage.xaml包含了本书会涉及到的绝大多数XML命名空间。尽管他们看上去像是URL,但他们实际上是一些特殊程序集的命名空间。

命名空间                                                        前缀                             描述


http://schemas.microsoft.com/                无                           标准的Silverlight命名空间,包含了诸如Gird,

winfx/2006/xaml/presentation                                                Button和TextBlock等元素。

http://schemas.microsoft.com/                x                             XAML语言的命名空间。包含了诸如Class,

winfx/2006/xaml                                                                   Name和Key等关键字

clr-namespace:Microsoft.Phone.              phone                       手机特有的Silverlight控件的命名控件,包含了

Controls;assembly=Microsoft.Phone                                        PhoneApplicationPage等。

clr-namespace:Microsoft.Phone.Shell;      shell                          这个命名空间是关于手机上不同于基础

assembly=Microsoft.Phone                                                     Silverlight元素的部分:status bar

                                                                                           和application bar

http://schemas.microsoft.com/               d                             这个命名空间提供设计时的信息,可以为

expression/blend/2008                                                          Expression Blend和Visual Studio提供预览。

http://schemas.openxmlformats.org/     mc                           可以标记的兼容性命名空间。可以用来标记其他

markup-compatibility/2006                                                   命名空间或元素可以被忽略。一般在设计时使

                                                                                         用,在运行时会被忽略。


    前面的三个命名空间基本上总会用到。shell命名空间只用在页面使用了ApplicationBar类或者status bar(设置SystemTray.IsVisible为True)的时候。status bar是手机的顶部区域,用于显示时间,信号强度,电量等信息。作为开发者,你只能显示或隐藏它。

    最后的两个命名空间,会在每个页面里插入mc:Ignorable,d:DesignWidth,和d:DesignHeight,是页面很混乱,所以本书的很多例子都移除了这两个命名空间。这会在Visual Studio的设计视图和Expression Blend产生负面的影响。如果影响到了使用,可以添加回这两个命名空间。当你对页面进行修改的时候,Visual Studio也会自作主张地加入它们。

light

如果你纠结于Visual Studio打开XAML文件时的龟速,同时你也不需要对页面进行预览。那么,你可以考虑修改默认的XAML编辑器。在解决方案资源管理器(Solution Explorer)中,右键点击XAML文件,选择打开方式(Open With),XML(Text)Editor,点击设为默认值(Set as Default),然后点击OK。这样会导致一些问题,比如没有了智能感知,但是速度会快上许多。

手机主题资源

    不同于硬编码的字体,字号大小和颜色,MainPage.xaml通过StaticResouce来调用手机特有的资源。Windows Phone定义来一些资源,使得应用可以与用户的主题保持协调一致。这些资源不仅包括特别的颜色,刷子,字体,字号和厚度(关于边框和margin/padding),同时还包含一些针对textblock的样式。

    在这个页面里使用的资源是:
    ➔ PhoneFontFamilyNormal — Segoe WP
    ➔ PhoneFontSizeNormal — 20 px (15 pt)
    ➔ PhoneForegroundBrush — 一个填充刷子,在黑色主题下是白色,在白色主题下市黑色
    ➔ PhoneTextNormalStyle — 前面3个的组合:PhoneFontFamilyNormal的FontFamily,PhoneFontSizeNormal的字体大小, 和PhoneForegroundBrush的前景色
    ➔ PhoneTextTitle1Style — PhoneFontFamilySemiLight的FontFamily (Segoe WP Semilight), PhoneFontSizeExtraExtraLarge的字体大小(72 px, which is 54 pt), 和PhoneForegroundBrush的前景色

warning

避免使用硬编码的颜色,除非已经包含进来主题的颜色
    你应当尽可能地尊重用户的主题(以及Windows Phone的设计指导)。如果你想完全控制色调,就必须考虑用户主题可能会造成的影响。比如,使用一个硬编码的白色文字,在黑色主题默认背景下看上去没问题。但是如果是在白色主题下,则根本看不见。在黑色图片上使用标准的按钮,在黑色主题下也没问题(因为按钮的文字和边框都是白色的)。但是在白色主题下面几乎就看不见(因为按钮的文字和边框都是黑色的)。

question

Outlook总是使用白色主题而IE总是使用的黑色主题,而无视用户设置。我自己的应用也能自由选择主题吗?
    基本不能。你当然可以使用自己的颜色,而无视或者覆盖掉主题资源,但你不能修改状态条的颜色,只能隐藏它。

light

Segoe WP字体,及其变体,是专门为Windows Phone而生的。在系统和应用的每个地方都在用它。所以,除非有非常明确的目的(比如编写的是游戏或者是个阅读器),使用其他的字体都会看起来很奇怪。

MainPage.xaml.cs

MainPage.xaml.cs

 

warning

永远不要删除代码后置文件的构造函数中对InitializeComponent的调用
    InitializeComponent将XAML声明的内容和类运行时的实例关联起来。

App.xaml和App.xaml.cs

    App.xaml是一个特殊的XAML文件,没有定义任何的可见性,但是它定义了一个App的类,可以完成程序级的任务。一般而言,修改这个文件的唯一原因,就是要设置一些程序级的资源(比如用户样式)在它的Application.Resource节点中。
    App.xaml.cs引人注目的工作就是处理来程序生命周期里面的事件(Launching,Activated,Deactivated和Closing)。

AssemblyInfo.cs

    在本书中,这个文件没有什么价值。它包含了一组属性(设置标题,描述,公司名称,版权声明等等),最终会编译到你的程序集中。因为MarketPlace中的所有信息都不是在这里管理的,所以没有必要设置它们。
    尽管如此,AssemblyVersion和AssemblyFileVersion(一般都设置相同的值),可以用来区分程序的不同版本。

修改默认项目创建“Tally”

    现在,我们了解来新创建的Visual Studio项目都包含来什么,可以开始修改它来创建Tally了。
    首先,我们可以移除所有应用清单中的功能,只暂时保留ID_CAP_NETWORKING用来在手机上测试我们的应用。

<Capabilities>
    <!-- None needed -->
    <!-- TODO: This is only for debugging on a device: -->
    <Capability Name="ID_CAP_NETWORKING" />
</Capabilities>

    我们也可以修改这两个图标文件,同时删除闪屏图片。现在就准备开始修改MainPage.xaml和MainPage.xaml.cs了。

更新UI

修改后的MainPage.xaml

    ➔ 不需要的属性都被删掉了,顶部的两个text block也更新了,旧的ContentGrid也被替换成了text block和按钮。grid中加入了第三行用来盛放按钮。
    ➔ text block和reset按钮分别赋予了CountTextBlock和ResetButton的名字,这样就可以方便地在代码后置文件中引用。
    ➔ 页面的字体大小修改为PhoneFontSizeHuge(186.667px/140pt)。这个值仅影响到CountTextBlock,其它的text block都使用来自己的样式。ResetButton中的文字没有继承到页面级的文本属性。
    ➔ 重置按钮有一个Click事件,触发后台声明的ResetButton_Click。

更新代码后置文件

代码后置文件是Tally工作所需要的逻辑部分。

修改后的MainPage.xaml.cs

question

为什么Windows Phone会使用鼠标事件(MouseLeftButtonDown)?手机就没有鼠标!
    这是一个和桌面版本的Silverlight兼容性有关的问题。尽管确实有touch和mutli-touch这些事件,简单的单个手指的行为,一般还是看作鼠标的事件(比如MouseLeftButtonDown,MouseMove和MouseLeftButtonUp)。这是因为,这些事件工作起来比touch事件要简单。所以很多应用是使用这种听上去很奇怪的事件。把你的手指看作鼠标指针,屏幕看作左键,这样就好理解点了。

    ➔ 一般情况下,一个类如果提供了XXX事件的话,同时也会提供OnXXX方法,供子类来重写。通过重写OnMouseLeftButtonDown,当触碰到页面的任何地方的时候(除了按钮),代码都可以有效地处理页面的MouseLeftButtonDown事件。这正好是我们需要触发计数加一,同时更新TextBlock属性的条件。因为按钮内部处理这个事件来避免特别的行为,所以在触碰按钮的时候,又不会触发这个方法。这样可以防止按钮的触碰,冒泡到页面上。
    ➔ “N0”是计数转换为字符串时候的格式。表示“按自然数显示(有千位分隔符)”。千位分隔符一般应用于United States English,但是会根据手机的“region & language”设置来自动变化。
    ➔ 按钮有自己的事件来处理触碰(Click),用来替代原本的MouseLeftButtonDown事件。当触碰的时候,按钮不会被触发;当抬起的时候,才会触发。按钮在按下的时候会高亮自己,当手指离开的时候则恢复同时触发Click事件。这个按钮的Click事件(ResetBuuton_Click)重置了计数,同时更新TextBlock的值。
    ➔ 在OnNavigatedFrom/OnNavigatedTo方法中,使用的Setting成员(savedCount),提供了一种简单的方法来存储应用的状态。当用于离开应用的时候,记录下计数;当用户回来的时候恢复计数(甚至用户重启手机也可以恢复)。
    ➔ 记得更新TextBlock。让文本保持随计数变化而变化,是很容易出错的地方,特别是在更大的应用中。使用从属属性(dependency property)会更简单而不易错。为了保持简单,暂时不使用这种方法。

question

为什么Click事件是在手指离开的时候触发,而不是按下的时候触发?
    虽然乍一听起来会显得奇怪,但这不论在桌面还是手机平台上都是很标准的行为。好处就在于,这种方式可以给用户一个反悔的机会(比如按到了错误的按钮),只要简单的将手指移到按钮外面,就可以撤销掉。尽管如此,按钮也支持另外两种Click模式。如果你设置按钮的ClickMode为Press,按钮一被按下就会触发Click。如果设置为Hover,则手指滑过它的时候,就会触发Click事件了。你应该尽量避免使用这些模式,这会使用户变得很困惑。

posted @ 2011-08-27 00:08  penbox  阅读(1073)  评论(6编辑  收藏  举报