boundingRectWithSize 为多行标签返回错误的高度值

Posted

技术标签:

【中文标题】boundingRectWithSize 为多行标签返回错误的高度值【英文标题】:boundingRectWithSize returning a wrong height value for a multiline label 【发布时间】:2016-02-10 16:43:51 【问题描述】:

boundingRectWithSize 和使用 Swift 语言的多行 UILabel 遇到了一个奇怪的问题。我目前在 Xcode 游乐场工作,因此可以实时查看 UI 的结果和更新。

我要做的是根据它的内容动态计算给定的 UILabel 高度,我知道这已经在其他 *** 问题中讨论过,但这对我来说似乎太奇怪了。

多行标签以NSAttributedString 形式包含此文本。文本是一个简单的 Lorem ipsum 占位符:

Lorem ipsum dolor sit amet,consectetur adipiscing elit。 Donec a diam lectus。 Sed 坐 amet ipsum mauris。 Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit。 Donec et mollis dolor。

这是UILabel的代码:

let valueString = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor."

var dataValue = UILabel()
dataValue.numberOfLines = 0
dataValue.lineBreakMode = .ByWordWrapping

let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = .Justified
paragraphStyle.lineBreakMode = .ByWordWrapping
paragraphStyle.firstLineHeadIndent = 0.1

let attributedText = NSAttributedString.init(
    string:valueString,
    attributes:[NSParagraphStyleAttributeName:paragraphStyle, NSFontAttributeName:dataValue.font])

let textString = dataValue.text! as NSString

dataValue.attributedText = attributedText

dataValue.frame = CGRect(
                x:CGFloat(kMargin),
                y:dataType.frame.origin.y + CGFloat(kLabelHeight),
                width:CGFloat((maxLabelWidth) - kMargin * 2),
                height:textString.boundingRectWithSize(
                    CGSizeMake(CGFloat(kMaxWidth), CGFloat.max),
                    options:[.UsesLineFragmentOrigin, .UsesFontLeading],
                    attributes:[NSParagraphStyleAttributeName:paragraphStyle, NSFontAttributeName:dataValue.font],
                    context:nil).size.height)

问题在于 UILabel 只显示 3 行文本,停在文本的 ma​​uris 单词处并截断最后一行,正如您从 Playground 预览功能中看到的那样:

【问题讨论】:

【参考方案1】:

一个明显的问题是valueStringtextString 是两个不同的字符串。所以没有理由相信您放入标签的字符串与您正在测量的字符串相同。

你在这里使用valueString

let attributedText = NSAttributedString.init(
string:valueString, // ...

但你在这里使用dataString

height:textString.boundingRectWithSize(

另外,不要尝试将标签属性与属性文本结合起来。这可能会导致各种问题。 dataValue 标签应该没有font。您不应该获取此 font 值。使用属性字符串做所有事情。你不应该构建两个不同风格的字典;您应该分配和测量完全相同的属性字符串

换句话说,无论有无属性,都不要测量valueStringtextString。测量attributedString

最后,确保标签的宽度与您在测量期间使用的宽度相同。你在说

CGSizeMake(CGFloat(kMaxWidth) // ...

但没有证据表明标签本身会具有这个宽度。

【讨论】:

你好@matt 谢谢你的回答,我已经更新了我的问题,明确表示我正在阅读相同的文本值 不,你没有。我在您的问题中没有看到关于 textString 可能是什么的信息。 好吧,现在您只是在更改您的代码。所以现在我不相信你说的是你的代码真的是你的代码。 :) 是的,我知道,你是对的,所以我正在更新它以更好地模拟这里的真实情况,我第一次写问题时没有正确复制粘贴我的代码。现在可以看看吗?

以上是关于boundingRectWithSize 为多行标签返回错误的高度值的主要内容,如果未能解决你的问题,请参考以下文章

调用 NSAttributedString.boundingRectWithSize 时应用程序崩溃

boundingRectWithSize 有时会返回大约 1 行高的高度

boundingRectWithSize:options:attributes:context用法

adjustsFontSizeToFitWidth 或 boundingRectWithSize 何时更改 context.actualScaleFactor?

mysql 标量子查询和非法子查询

ios7 - boundingRectWithSize:boundingSize 不返回所需的标签高度