以编程方式确定文本框中的最大拟合(WP7)

时间:2011-02-27 01:04:08

标签: silverlight windows-phone-7 textblock measure

我目前正在为Windows Phone Seven编写电子书阅读器,我正试图像Kindle阅读器一样设计它。为了做到这一点,我需要将我的书分成页面,当添加可变字体大小时,这会变得更加复杂。

为了做到这一点,我只是一次在文本块中添加一个单词,直到它变得高于其容器。你可以想象,如果有超过120,000字的文件,这将花费一段不可接受的时间。

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

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

提前致谢!

4 个答案:

答案 0 :(得分:4)

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

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

  • 如果你改变字体大小,那么页面上的第一个单词保持不变(这就是%来自的地方) - 所以Kindle应用程序只做了一页的重写,假设第一个单词是页面保持不变。

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

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

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

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

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

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

答案 1 :(得分: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将书籍拆分成页面。 RegEx的这个站点上有一些例子,它们会在特定长度后打破字边界。


另一种选择是提前计算每个潜在字体大小的页面大小(并使用switch语句对其进行硬编码)。如果你允许任何字体和任何大小的组合,这可能很容易变得疯狂,如果你允许混合字体/大小,但是表现很好会很糟糕。很可能你有一个特定范围的可读大小,只有几种字体。创建一个测试应用程序来计算每个组合的页面文本长度并不会那么难,并且可能会让您的生活更轻松 - 即使它不像程序员那样“感觉”正确:)

答案 2 :(得分:1)

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

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

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

您还可以查看有关Page Transitions in Windows Phone的此文章以及有关final touches in the E-Book project的其他文章。

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

答案 3 :(得分:0)

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