使用自定义字体计算NSString的高度

时间:2012-11-25 14:38:20

标签: objective-c ios

我正试图解决这个问题一个星期了,我已经测试了很多想法,但我无法用自定义字体正确计算NSString的大小。< / p>

我的UITextView包含文字和UIView,我在UITextView上为这些行绘制了行号。问题是NSString UIKit添加在计算NSString的大小时忽略标签宽度。

在图片中,您可以清楚地看到第7行,这是在UITextView中呈现时换行符,之后所有行都会受到影响。

Simulator screenshot

我使用的字体是Adobe Source Code Pro

我已尝试NSString UIKit添加的所有方法但没有成功。

sizeWithFont

sizeWithFont:forWidth:lineBreakMode:

sizeWithFont:minFontSize:actualFontSize:forWidth:lineBreakMode:

我还尝试用四个空格替换字符串中的所有标签,这有帮助,但它仍然不能一直工作。对某些线路而言,它有所帮助,但有些线路没有。

如何正确计算NSString身高的任何建议?可能CoreText

一个小小的说明。我也尝试使用UITextInput协议中的几何命中测试方法解决这个问题,当它们工作时,cpu加载在模拟器上是100%,所以在真实设备上它会杀死应用程序,特别是如果我加载文件这是大约1500多行代码。

以下是我用于LineNumbersView.m的代码的要点。

1 个答案:

答案 0 :(得分:1)

假设UITextView和核心文本总是完全一致,那么后者绝对是一个解决方案,尽管对于这个问题并不是非常简单。

你最好:

  1. 在主视图中创建文本的属性字符串,并在整个范围内设置适当的字体;
  2. 为属性字符串创建合适的框架设置器(使用CTFramesetterCreateWithAttributedString);
  3. 创建一个CGPath,用于描述字符串将被绘制的绘图区域(作为UIBezierPath,然后获取CGPath属性或创建一个并使用{{3 }});
  4. 因此从framesetter创建一个框架加上路径加上你感兴趣的字符串的子范围,这可能就是全部(参见CGPathAddRect);
  5. 然后你可以从框架中获得它将输出的CFArray个单独的行(使用CTFramesetterCreateFrame),尽管这些是屏幕上的排版行,而不是你的源行;
  6. 对于每一行,您可以获得它包含的原始字符串的范围(使用CTFrameGetLines),允许您确定在原始换行符之后立即开始,而不是由于自动换行;
  7. 您还可以获得CGPoint个C数组,其中每个数组代表屏幕行的起源(CTLineGetStringRange);通过使用你在(6)中学到的东西来查找位置,你可以获得相关线的屏幕上的起源。
  8. 为了增加乐趣,Core Text的像素输出在OS X和iOS上是相同的。但是OS X认为屏幕的原始位置是左下角,就像方格纸一样。 iOS将其视为左上角,如英语阅读顺序。大致措辞的净效应是iOS Core Text上下颠倒。所以你需要考虑到这一点。在iOS术语中,您显然会看到第一行位于帧的最底部,第二行是在其上方的一行,等等。您需要翻转这些坐标。

    即使你正在经历如此多的箍,它可能最终只会有大约一百行代码。