似乎无法为 UILabel 计算正确的 NSAttributedString 行高
Posted
技术标签:
【中文标题】似乎无法为 UILabel 计算正确的 NSAttributedString 行高【英文标题】:Can't seem to calculate correct line-height of NSAttributedString for a UILabel 【发布时间】:2014-04-07 15:19:47 【问题描述】:阅读this article from objc.io后,我正在使用NSAttributedString's
boundingRectWithSize:options:context:
方法计算某些文本的预期高度
+(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:
的一个潜在错误。我想出了一个解决方法:创建一个虚拟UILabel
,赋予它与表格视图单元格中的UILabel
相同的属性(numberOfLines
等),然后使用sizeThatFits:
计算大小。可以肯定的是,这是一个 hack - 但它充分解决了我的问题。不过,我希望它更优雅!
【问题讨论】:
【参考方案1】:我在尝试计算 UITextView 的属性文本大小时遇到了同样的效果。我遇到了this answer to another question。
诀窍是使用NSLayoutManager's usedRectForTextContainer:
。巧妙的是,此方法不需要与 UITextView 结合使用。这意味着您可以在 mainThread 之外使用它,这是预先计算 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。我对整个编程有点陌生,所以如果我的代码可以优化,请告诉我。
【讨论】:
【参考方案2】:我想,你可能没有设置preferredMaxLayoutWidth
。
此属性将约束设置为视图的最大宽度。
【讨论】:
以上是关于似乎无法为 UILabel 计算正确的 NSAttributedString 行高的主要内容,如果未能解决你的问题,请参考以下文章
UITableViewCell 计算正确的高度,但 UILabel 不换行
UICollectionViewCell 中的 UILabel 有时无法正确调整大小
为啥我在 UITableCellView 中的 UIView 中的 UILabel 在正确的数据库调用后没有更新(似乎与单元重用有关)?