5

我目前正在为 Windows Phone 7 编写一个电子书阅读器,并且我正在尝试将它的样式设置为 Kindle 阅读器。为了做到这一点,我需要将我的书分成几页,当添加可变字体大小时,这将变得更加复杂。

目前要做到这一点,我只需将一个单词一次添加到文本块中,直到它高于其容器。您可以想象,对于超过 120,000 字的文档,这需要一段不可接受的时间。

有没有一种方法可以找出文本何时超出界限(逻辑上将其划分为页面),而无需实际呈现它?这样我就可以在后台线程中运行它,这样用户就可以同时继续阅读。

到目前为止,我想到的唯一想法是找出文本块如何决定其边界(在测量调用中?),但我不知道如何找到该代码,因为反射器没有显示任何内容。

提前致谢!

4

4 回答 4

4

据我所知,Kindle 应用程序似乎使用了与您建议的算法相似的算法。注意:

  • 它通常显示整本书的百分比位置 - 它不显示总页数。

  • 如果您更改字体大小,则页面上的第一个单词保持不变(这就是 % 的来源) - 因此,假设页面的第一个单词保持不变,Kindle 应用程序只需进行一页的重新分页。

  • 如果您更改字体大小然后滚动回第一页,那么实际上存在不连续性 - 他们再次向前拉内容以填充第一页。

基于此,我建议您不要索引整本书。相反,只需专注于基于某种“位置”的当前页面(例如字符数 - 显示为百分比)。如果您必须在后台线程上做某事,那么只需查看下一页(可能还有上一页),以便滚动可以更具响应性。

为了进一步优化您的体验,您可以尝试对当前算法进行一些更改:

  • 为您的算法尝试不同的起点和搜索增量 - 无需从一个单词开始,然后一次只添加一个单词。

  • 假设您的大多数书籍都是 ASCII,请尝试缓存常用字符的宽度,然后自己计算文本块的宽度。

除此之外,我还很想尝试<Run>在 TextBlock 中使用块 - 有可能获得 TextBlock 中每个 Run 的相对位置 - 尽管我还没有设法做到这一点。

于 2011-02-27T18:41:40.413 回答
3

I do something similar to adjust font size for individual textboxes (to ensure they all fit). Basically, I create a TextBlock in code, set all my properties and check the ActualWidth and ActualHeight properties. Here is some pseudo code to help with your problem:

public static String PageText(TextBlock txtPage, String BookText)
{
    TextBlock t = new TextBlock();
    t.FontFamily = txtPage.FontFamily;
    t.FontStyle = txtPage.FontStyle;
    t.FontWeight = txtPage.FontWeight;
    t.FontSize = txtPage.FontSize;
    t.Text = BookText;

    Size Actual = new Size();
    Actual.Width = t.ActualWidth;
    Actual.Height = t.ActualHeight;

    if(Actual.Height <= txtPage.ActualHeight)
        return BookText;

    Double hRatio = txtPage.ActualHeight / Actual.Height;
    return s.Substring((int)((s.Length - 1) * hRatio));
}

The above is untested code, but hopefully can get you started. Basically it sees if the text can fit in the box, if so you're good to go. If not, it finds out what percentage of the text can fit and returns it. This does not take word breaks into account, and may not be a perfect match, but should get you close.

You could alter this code to return the length rather than the actual substring and use that as your page size. Creating the textblock in code (with no display) actually performs pretty well (I do it in some table views with no noticeable lag). I wouldn't send all 120,000 words to this function, but a reasonable subset of some sort.

Once you have the ideal length you can use a RegEx to split the book into pages. There are examples on this site of RegEx that break on word boundaries after a specific length.


Another option, is to calculate page size ahead of time for each potential fontsize (and hardcode it with a switch statement). This could easily get crazy if you are allowing any font and any size combinations, and would be awful if you allowed mixed fonts/sizes, but would perform very well. Most likely you have a particular range of readable sizes, and just a few fonts. Creating a test app to calculate the text length of a page for each of these combinations wouldn't be that hard and would probably make your life easier - even if it doesn't "feel" right as a programmer :)

于 2011-03-01T14:28:19.373 回答
1

我没有找到微软对这个示例的任何引用:“分页原则”。

它有一些在 Windows Phone 中运行的有趣示例代码。

http://msdn.microsoft.com/en-us/magazine/hh205757.aspx

您还可以查看有关Windows Phone 中的页面转换的文章和有关E-Book 项目最后润色的其他文章。

代码可下载: http: //archive.msdn.microsoft.com/mag201111UIFrontiers/Release/ProjectReleases.aspx?ReleaseId =5776

于 2013-09-08T22:05:34.220 回答
0

您可以查询在 textBlock 中使用 AFAIK 的 FormattedText 类。因为这是用于格式化文本以准备渲染的类,所以这是可用的最低级别的类,并且应该很快。

于 2011-02-27T04:09:26.187 回答