2011-02-27 42 views
5

我目前正在为Windows Phone Seven编写电子书阅读器,并且试图将其设置为像Kindle阅读器一样。为了做到这一点,我需要将书籍拆分成多个页面,并且在添加可变字体大小时这会变得更加复杂。以编程方式确定文本框中的最大适合度(WP7)

要做到这一点,我只是一次添加一个单词到文本块,直到它变得高于它的容器。可以想象,尽管有超过120,000字的文档,这需要一段难以接受的时间。

有没有一种方法,我可以找出什么时候文本会超出边界(逻辑上划分成页面),而不必实际渲染它?这样我就能够在后台线程中运行它,以便用户可以在此期间继续阅读。

到目前为止,唯一出现的想法是找出textblock如何确定其边界(在度量调用中?),但我不知道如何找到该代码,因为反射器没有显示任何东西。

在此先感谢!

回答

3

我做类似的调整个别文本框的字体大小的东西(以确保它们都适合)。基本上,我在代码中创建一个TextBlock,设置我所有的属性并检查ActualWidth和ActualHeight属性。下面是一些伪代码,以帮助您的问题:

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)); 
} 

以上是未经测试的代码,但希望能得到你开始。基本上它会看到文本是否可以放在盒子里,如果你愿意的话。如果不是,它会找出文本的百分比可以适合并返回。这不会考虑分词,也可能不是完美匹配,但应该让你接近。

你可以改变这个代码返回长度而不是实际的串并使用它作为你的页面大小。在代码中创建文本块(没有显示)实际上表现很好(我在一些表格视图中执行,没有明显的延迟)。我不会发送所有120,000字到这个函数,而是一些合理的子集。

一旦你有理想的长度,你可以使用正则表达式的书分成页。 RegEx的这个网站上有一些例子,在特定长度之后在单词边界上突破。


另一个选择是为每个可能的字体大小提前计算页面大小(并用switch语句对它进行硬编码)。如果您允许任何字体和任何大小的组合,这很容易让人抓狂,如果您允许混合字体/大小,将会很糟糕,但性能会非常好。很可能你有一个特定的可读大小范围,只有几个字体。创建一个测试应用程序来计算这些组合的每个页面的文本长度不会那么硬,很可能会令您的生活更轻松 - 即使它没有“感觉”的权利,作为一个程序员:)

+0

我会试试看,以前没有单纯从代码中尝试。 – 2011-04-07 11:19:20

+0

注释为答案,因为这是我的问题的最佳答案。可能不是我通过的路线。 – 2011-04-07 11:19:47

0

您可以查询在textBlock中使用AFAIK的FormattedText类。由于这是用于为准备渲染而设置文本格式的类,因此这是最低级的可用类,并且速度应该很快。

+0

不幸的是,这只是一个WPF结构。 – 2011-02-27 05:46:32

4

从我所看到的Kindle应用程序似乎使用一个类似的算法,你的建议。请注意:

  • 它通常显示通过本书的%位置 - 它不显示总页数。

  • 如果更改字体大小,那么页面上的第一个单词保持不变(所以这就是%的来源) - 所以Kindle应用程序只是假设页面的第一个单词有一页值得重新分页保持不变。

  • 如果更改字体大小然后回滚到第一页,那么实际上会出现不连续性 - 为了填充第一页,它们再次将内容向前拉。

在此基础上,我会建议你做指数整本书。相反,只需根据某种“职位”(例如,字符数 - 以百分比显示)专注于当前页面。如果您必须在后台线程上执行某些操作,那么只需查看下一页(也可能是前一页),以便滚动更具响应性。

进一步优化您的经验,也有一些改动,你可以让你的当前算法,你可以尝试:

  • 争取你的算法,不同的出发点和搜索增量 - 无需从一个单词开始,然后一次只添加一个单词。

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

除此之外,我也想挺喜欢使用的TextBlock内<Run>块尝试 - 这可能让每个TextBlock的范围内运行的相对位置 - 尽管我还没有成功地做到这一点然而。

+0

嗯。我想这可能是为什么你不能快速滚动几页来结束。我会考虑这一点,但我仍然感到惊讶,似乎没有办法合理地进行手动“测量”。 – 2011-02-28 06:35:35

+0

+1,你描述它的方式,Kindle设备也可以。并且你所提出的建议是我可以做出的唯一建议(也就是编写wp7阅读器:)) - 使用代码内TextBlock在页面之后分页。 – jumbo 2011-03-11 09:12:23

相关问题