为UILabel计算NSAttributedString的正确行

为UILabel计算NSAttributedString的正确行

本文介绍了似乎无法为UILabel计算NSAttributedString的正确行高的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 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的正确行高的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-02 07:39