似乎无法为UILabel计算NSAttributedString的正确行高
我正在使用NSAttributedString's
boundingRectWithSize:options:context:
方法来计算某些文本的预期高度, 从objc.io阅读本文后
+(CGSize)postLabelSizeForPost:(ANKPost *)post { CGFloat labelWidth = 220.0f; NSAttributedString *text = [BXTPostCell mutableAttributedStringForPost:post]; NSStringDrawingOptions options = NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading; CGRect boundingRect = [text boundingRectWithSize:CGSizeMake(labelWidth, CGFLOAT_MAX) options:options context:nil]; CGFloat height = (CGFloat) (ceil(boundingRect.size.height)); return CGSizeMake(labelWidth, height); }
但是,当我使用这种方法时,文本实际上并不适合这个大小 – 大小一直太短。
起初,我认为这个问题与表情符号有关 – 但它似乎正在应用程序中的许多tableviewcells中发生。
更新:我和一些人聊过,听起来这个问题可能是boundingRectWithSize:options:context:
一个潜在错误boundingRectWithSize:options:context:
. 我想出了一个解决方法:创建一个虚拟的UILabel
,给它与tableview单元格中的UILabel
相同的属性( numberOfLines
等),然后使用sizeThatFits:
来计算大小。 这是一个黑客,当然 – 但它足以解决我的问题。 不过我希望它更优雅!
在尝试计算UITextView的属性文本大小时,我遇到了同样的效果。 我在另一个问题上遇到了这个答案 。
诀窍是使用NSLayoutManager的usedRectForTextContainer:
. 什么是整洁的是这个方法不需要与UITextView一起使用。 这意味着您可以将它从mainThread,key用于预先计算UITableViewCell高度。
这是我如何使用它:
- (CGSize)rectForAttributedString:(NSAttributedString *)string withSize:(CGSize)theSize { if (!string || CGSizeEqualToSize(theSize, CGSizeZero)) { return CGSizeZero; } // setup TextKit stack NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:theSize]; NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:string]; NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init]; [layoutManager addTextContainer:textContainer]; [textStorage addLayoutManager:layoutManager]; // query for size CGRect rect = [layoutManager usedRectForTextContainer:textContainer]; return CGSizeMake(ceilf(rect.size.width), ceilf(rect.size.height)); }
为了简化操作,我创建了一种方便的方法来计算特定宽度的高度:
- (CGFloat)textViewHeightForAttributedString:(NSAttributedString *)string withWidth:(CGFloat)width { return [self rectForAttributedString:string withSize:CGSizeMake(width, CGFLOAT_MAX)].height; }
希望这可以帮助。
PS。 我对这整个编程问题都很陌生,所以如果我的代码可以优化,请告诉我。
我想,你可能不会设置preferredMaxLayoutWidth
。
此属性将约束设置为视图的最大宽度。