获取估计的属性字符串高度而不使用文本视图

时间:2016-06-27 14:05:09

标签: ios nsattributedstring

这个问题偶尔会出现,但我还没有找到可靠的解决方案。

我想准确估计NSAttributedString的高度,而不必将文本放入不可见的文本视图中以获得真正的高度。 (文本视图方法需要更多的处理时间)。但是我无法通过使用boundingRectWithSize获得始终如一的可靠值。它足够接近我的目的9次10,但这还不够好,因为它偶尔会导致截断的视图,其中一行文字不可见。

我的示例代码如下。输出是:

2016-06-27 08:54:17.106 TextHeightTest[14045:7574151] estimated1  225.000000
2016-06-27 08:54:17.108 TextHeightTest[14045:7574151] estimated2  209.000000

第一个值是正确的。

在.h文件中:

@interface ViewController : UIViewController {
    NSMutableDictionary *attributes;
    UIFont *font;
    UITextView *sizingTextView;
    CGFloat width;
}

在.m文件中:

- (void)viewDidLoad {
    [super viewDidLoad];

    sizingTextView = [[UITextView alloc] init];
    font = [UIFont fontWithName:@"Helvetica" size:20];
    width = 300;

    NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
    paragraphStyle.alignment = NSTextAlignmentLeft;
    paragraphStyle.lineSpacing = 7;
    paragraphStyle.maximumLineHeight = 20;
    paragraphStyle.minimumLineHeight = 20;

    attributes = [[NSMutableDictionary alloc] init];
    [attributes setObject:paragraphStyle forKey:NSParagraphStyleAttributeName];
    [attributes setObject:font forKey:NSFontAttributeName];

    NSString *text = @"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.";
    NSAttributedString *attribStr = [[NSAttributedString alloc] initWithString:text attributes:attributes];

    CGFloat estimated1 = [self estimateInTextView:attribStr];
    NSLog(@"estimated1  %f", estimated1);

    CGFloat estimated2 = [self estimateInSpace:text];
    NSLog(@"estimated2  %f", estimated2);
}

- (CGFloat)estimateInTextView:(NSAttributedString *)text {
    sizingTextView.attributedText = text;
    return [sizingTextView sizeThatFits:CGSizeMake(width, CGFLOAT_MAX)].height;
}

- (CGFloat)estimateInSpace:(NSString *)text {
    CGRect rect = [text boundingRectWithSize:CGSizeMake(width, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:attributes context:nil];
    return CGRectGetHeight(rect);

}

我感谢任何帮助。感谢。

2 个答案:

答案 0 :(得分:2)

文本视图将文本放在文本容器中。默认情况下,文本容器在顶部和底部插入8个点。请参阅textContainerInset的文档。因此,文本视图将比文本本身所需的空间高16个点。

由于文本容器的lineFragmentPadding,可能还存在基于宽度的换行差异,默认为左右5个点。不过,我不确定。

对于测试,您实际上可以在给定大小的矩形中绘制字符串,并将其与在相同大小的文本视图中呈现的字符串进行比较。查看线路是否在不同点处断开。在两者周围画一个框架,看看文本的位置不同。

答案 1 :(得分:0)

根据文档,“要使用返回的大小来调整视图大小,你必须使用ceil函数将其值提升到最接近的更高整数。”你应该四舍五入(尽管你的特定例子中这不是'似乎是问题所在。)