问题描述
我正在使用 NSAttributedString的
boundingRectWithSize:options:context:
计算某些文本的预期高度的方法,阅读后
I'm using NSAttributedString's
boundingRectWithSize:options:context:
method to calculate the expected height for some text, after reading this article from 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);
}
然而,当我使用这种方法时,文本实际上并不适合这个尺寸 - 尺寸一直太短。
However, when I use this method, the text doesn't actually fit inside this size - the size is consistently too short.
起初,我认为这个问题出现在表情符号中 - 但是应用程序中的许多tableviewcells似乎都在发生。
At first, I'd thought the issue was with emoji characters - but it seems to be happening for many tableviewcells in the app.
更新:
我和几个人聊过,听起来这个问题可能是 boundingRectWithSize的一个潜在错误:options :上下文
。我找到了一个解决方法:创建一个虚拟的 UILabel
,在tableview单元格中为它提供与 UILabel
相同的属性( numberOfLines
等)然后使用 sizeThatFits:
来计算大小。这是一个黑客,当然 - 但它足以解决我的问题。我希望它更优雅!
Update:I've talked with a few folks, and it sounds like the issue may be an underlying bug with boundingRectWithSize:options:context:
. I figured out a workaround: create a dummy UILabel
, give it the same attributes as the UILabel
in the tableview cell (numberOfLines
, etc) and then use sizeThatFits:
to calculate the size. It's a hack, to be sure - but it solves my problem sufficiently. I wish it were more elegant, though!
推荐答案
我在尝试计算属性文本的大小时遇到了同样的效果一个UITextView。我遇到了。
I came across this same effect when trying to calculate the size of attributed text for a UITextView. I ran across this answer to another question.
诀窍是使用。什么是整洁的是这个方法不需要与UITextView一起使用。这意味着你可以在mainThread上使用它,用于预先计算UITableViewCell高度的键。
The trick is to use NSLayoutManager's usedRectForTextContainer:
. What is neat is that this method doesn't need to be used in conjunction with a UITextView. This means that you can use it off of the mainThread, key for pre-calculation of UITableViewCell heights.
以下是我如何使用它:
- (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));
}
为了方便起见,我创建了一种方便的方法来计算出的高度特定宽度:
To make things easier, I created a convenience method to figure out the height for a specific width:
- (CGFloat)textViewHeightForAttributedString:(NSAttributedString *)string withWidth:(CGFloat)width
{
return [self rectForAttributedString:string withSize:CGSizeMake(width, CGFLOAT_MAX)].height;
}
希望这有帮助。
PS。我对这整个编程工作都很陌生,所以如果我的代码可以优化,请告诉我。
这篇关于似乎无法为UILabel计算NSAttributedString的正确行高的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!