《101 Windows Phone 7 Apps》读书笔记-BOOK READER

简介:

课程内容

Ø编页

ØList Picker

Ø拉伸List Box 控件中的条目

 

    本章的Book Reader应用程序为Jane Austen的经典小说《傲慢与偏见》提供一种专门为手机进行优化的阅读体验。书的字体来自Gutenberg项目(www.gutenberg.org),由于其版权已经过期,因此它为美国人民提供了免费的电子书。如果你打算发布一个包含Gutenberg项目的应用程序,确认你已经理解了Gutenberg项目的许可证。详见www.gutenberg.org

    为了达到最好的阅读体验,本应用程序允许用户自定义前景色、背景色、字体大小,甚至是字体集。Book Reader提供了简便的页面导航,允许用户跳转到任何章节或者任何页码。刚开始可能不那么明显,但是实现本应用程序的最大挑战是编页,即在字体设置的基础上为整本书的内容分页。当然,我们可以将整本书的内容放置在具有滚动条页面中,但这并不能够带来好的用户体验。另外,由于UI元素的大小限制,使用其他的方法也未必可行。因此,本应用程序一次只显示一个页面。用户可以通过点击屏幕来翻页,或者点击应用程序栏上的按钮来回退页面。

 

The Main Page

    图25.1显示了应用程序栏展开后的主页面,应用程序栏上具有回退一页按钮、跳转到任何章节或者页码的按钮和改变设置的按钮。应用程序栏区域同时也显示了当前页码和总页码(这是基于当前字体设置情况的)。

image

图 25.1 主页面图,默认使用类似Amazon Kindle的颜色模式,专门为阅读提供足够的对比度。

注意:

本应用程序的分页机制由PaginatedDocument用户控件来完成,在本章的最后详述。

命名为Footer的list box控件出现在应用程序栏中,因为它被放置在该区域的下方,而且应用程序栏的不透明度设置为0。

如图25.2所示的充满章节的list box,使用了一种非常重要但很难发现的方法,使得list box中的条目按照其宽度进行拉伸,填满该区域。这就可以在不给定宽度的条件下,使得每个条目中的元素(如页码)达到右对齐。

image

图25.2 使用HorizontalContentAlignment进行拉伸的list box,所以在不给定条目宽度的条件下,使得页码达到右对齐。

书本是以文本文件的形式包含进来的,其Build Action设置为Content,就和前一章中的数据库文件一样。文件的名称为1342.txt,与Project Gutenberg网站上下载来的文档一致。

本应用程序使用了如下的设置:读者当前的页码被存储为字符索引,即为包含了整本书的内容的页面的第一个字符建立索引。这是因为如果字体设置不同,那么与书本位置相关的页码也会不同。有了这个方法以后,用户在书本中的真正位置就被保存下来了。

添加到章节列表中的键值对是一种方便使用的类型,因为它包含了两个独立的字符串属性,数据模板可以将其绑定。其中,“Key”是左对齐的章节标题,“value”是右对齐的页码。

 

The Settings Page

    Book Reader的设置页面几乎与Notepad应用中的设置页面相同。其不同之处在于顶端的font picker,如图25.3所示。该font picker由Silverlight for Windows Phone Toolkit中的list picker控件创建而来。

imageimage

图25.3 font picker在WYSIWYG picker中显示的10种字体

    这里,List picker基本上就是一个combo box。它开始的时候看上去像text box,但是被点击的时候,它允许用户从列表中选择一个值。数据模板同时绑定每个text block的FontFamily和Text属性,在列表中显示每个字符串。List picker支持两种不同的列表展示方式:内联模式和全模式。如图25.3所示,内联模式中,该控件通过流畅的动画来对记录进行展开和合拢。如图25.4所示,在全模式中,该控件显示全屏的记录列表。

image

图25.4 配置为全模式的Book Reader中font picker

当我尝试在Windows Phone 应用程序中使用ComboBox控件时,为什么显得很奇怪?

    ComboBox是一个核心的Silverlight控件,它频繁地使用在网页中,但是,它没有为Windows Phone提供合适的设计风格。所以它一般不会被使用(该控件应该移除来避免困惑)。如果你想使用combo box的话,就用list picker来替代吧。

    如果记录的数量少于5个的话,List picker默认使用内联模式;不然的话,它会使用全模式。这与Windows Phone设计准则是一致的。但是,我们可以通过设置ItemCountThreshold的值来强制其中的一个模式。只要记录的数量少于等于ItemCountThreshold,List picker会保持内联模式。Book Reader的font picker保持10种字体的内联模式,所以其属性值设置为10.

    List picker定义了Header及其相关的HeaderTemplate属性,定义了ItemTemplate属性,用于自定义每个记录内联模式中的外观显示效果。即使我们使用全模式,对于list picker的外观来说,这些属性也是很重要的。对于全屏的列表,list picker同样定义了独立的FullModeHeader和FullModeItemTemplate属性。如图25.4所示,全屏模式的list picker利用了这两个属性。如果我们不指定FullModeItemTemplate,全模式会使用ItemTemplate。

使用全模式时,List pickers不能包含UI元素!

    如果我们直接把诸如text blocks或者toolkit中的ListPickerItem控件这些UI元素放置于list picker中,那么,在全屏模式显示时,会抛出异常。那是因为该控件尝试将每个记录加入到额外的全屏模式列表中,但是单个UI元素一次只能放置于一个地方。解决方法是在list picker中放置非可视化的数据记录,然后使用模板来控制每个记录的外观。

避免将内联模式的list picker放置于scroll viewer的底部!

    List picker在这种情况下不适合使用。当第一次展开时,屏幕内容不会被移动,这是为了确保内容保留在屏幕上。然后,当尝试着用滚动条来查看其他内容时,list picker会折叠起来。为了达到最好的性能,内联模式list picker下的元素应该将CacheMode设置为BitmapCache,那是因为list picker的下拉和收缩能够改变这些元素的位置。

List Pickers and Picker Boxes

    虽然单个list picker控件提供了两种不同的体验,但是一些Windows Phone方面的文章将全模式的list picker称为分离的picker box控件,它保留了内联模式体验中的term list picker。这正是为什么第19章“Animation Lab”中使用的自定义控件称为PickerBox的原因。

 

The PaginatedDocument User Control

    为了决定分页产生的位置,PaginatedDocument用户控件必须测量当前字体设置下,每个字符的宽度和高度。执行测量的唯一方式是将文本放置于text block中,并且检查其ActualWidth和ActualHeight属性的值。因此,PaginatedDocument将执行以下三个步骤的算法:

1. 查找文档中每个不同的字符(《傲慢与偏见》只包含了85个不同的字符)。

2. 通过向text block中放置每个字符来测量其宽度和高度,一次放置一个。所有字符的高度都是一样的(因为这里的高度是线高度,包含了填充和其它),因此,高度只需要测量一次。

3. 从头至尾浏览整篇文档,使用预先测量好的字符宽度来计算每个换行的地点。有了这个信息,以及之前测量的高度,我们就可以知道每个换页的地点。由于收缩部分单词的需求,决定换行符需要一些小技巧。

    基于计算得到的换页地点和换行地点,该控件为每一行文字增加一个text block来得到所有的页面。

注意:

换行与换页的索引分别存储在各自的列表中。存储换页的列表是换行列表的子集,这种关系在一个页面需要渲染时变得尤为清晰。

在UpdatePagination中,将尽可能多的工作交给后台线程来做。因为实际的测量工作必须在UI线程中完成,但是,两个后台辅助线程用来将一个后台线程过渡为主线程,然后再将其转回后台线程。

本控件对于输入的文本有一些假设,工程中包含的《傲慢与偏见》的文档经过了预处理,使得下面的假设成立:

1. 换行符(\n)表示强制的换行,它只在一段文字的末尾出现(原文使用固定的行宽度,因此定期放置\n就可以,这就无法完成输出的动态调整)。

2. 回车符(\r)代表新一章的开始。有了它的帮助,这就完成了章节集合总数的自动统计,使得可以将其显示在主页面的list box上。


本文转自施炯博客园博客,原文链接:http://www.cnblogs.com/dearsj001/archive/2012/08/13/101App4WP7_BookReader.html,如需转载请自行联系原作者


相关文章
|
16天前
|
Linux C++ Windows
【Azure 应用服务】Azure App Service(Windows)环境中如何让.NET应用调用SAP NetWeaver RFC函数
【Azure 应用服务】Azure App Service(Windows)环境中如何让.NET应用调用SAP NetWeaver RFC函数
【Azure 应用服务】Azure App Service(Windows)环境中如何让.NET应用调用SAP NetWeaver RFC函数
|
16天前
|
Java 应用服务中间件 开发工具
[App Service for Windows]通过 KUDU 查看 Tomcat 配置信息
[App Service for Windows]通过 KUDU 查看 Tomcat 配置信息
|
16天前
|
Java 应用服务中间件 Windows
【App Service for Windows】为 App Service 配置自定义 Tomcat 环境
【App Service for Windows】为 App Service 配置自定义 Tomcat 环境
|
16天前
|
PHP Windows
【Azure App Service for Windows】 PHP应用出现500 : The page cannot be displayed because an internal server error has occurred. 错误
【Azure App Service for Windows】 PHP应用出现500 : The page cannot be displayed because an internal server error has occurred. 错误
|
17天前
|
PHP 开发工具 git
【Azure 应用服务】在 App Service for Windows 中自定义 PHP 版本的方法
【Azure 应用服务】在 App Service for Windows 中自定义 PHP 版本的方法
|
16天前
|
网络安全 API 数据安全/隐私保护
【Azure App Service】.NET代码实验App Service应用中获取TLS/SSL 证书 (App Service Windows)
【Azure App Service】.NET代码实验App Service应用中获取TLS/SSL 证书 (App Service Windows)
|
16天前
|
Shell PHP Windows
【Azure App Service】Web Job 报错 UNC paths are not supported. Defaulting to Windows directory.
【Azure App Service】Web Job 报错 UNC paths are not supported. Defaulting to Windows directory.
|
16天前
|
存储 Linux Windows
【应用服务 App Service】App Service For Windows 如何挂载Storage Account File Share 示例
【应用服务 App Service】App Service For Windows 如何挂载Storage Account File Share 示例
|
16天前
|
应用服务中间件 nginx Windows
【Azure 应用服务】在App Service for Windows中实现反向代理
【Azure 应用服务】在App Service for Windows中实现反向代理
|
17天前
|
网络协议 Linux 网络安全
【Azure 应用服务】更便捷的方式抓取Azure App Service for Windows的网络包
【Azure 应用服务】更便捷的方式抓取Azure App Service for Windows的网络包
下一篇
DDNS