带有单行文本的 UILabel 的行间距

Posted

技术标签:

【中文标题】带有单行文本的 UILabel 的行间距【英文标题】:Line Spacing for UILabel with a single line of text 【发布时间】:2015-11-24 07:10:43 【问题描述】:

具有自定义 lineSpacing 属性的多行 UILabel 是否应该包含该行间距,即使标签的文本适合一行?

这是我的标签:

let label = UILabel()
label.numberOfLines = 4
var paragraph = NSMutableParagraphStyle()
paragraph.lineSpacing = 5
paragraph.lineBreakMode = .ByTruncatingTail
label.attributedText = NSAttributedString(string: "Some short text", attributes: [NSParagraphStyleAttributeName: paragraph])

这是它的布局方式。请注意文本下方的额外间距。

比较:

奇怪的是缺乏一致性。当标签延伸到第二行时,底线不再包含这个额外的间距:

当只有一行文本时,有没有办法去除这个行距?或者其他一些强制一致性的方法,以便我至少可以解释它?

更新

基线计算似乎也被破坏了。当尝试将视图(此处为红色框)与标签的基线对齐时,多行标签会被部分覆盖。

【问题讨论】:

您使用的是自定义字体吗? @larsacus 是的,我是。具体来说,各种 Gotham 变体。 你试过用系统字体做同样的测试吗? FWIW 我已经验证即使使用系统字体也​​会发生这种情况。只要 UILabel 中的属性只要文本属性在字符串中的某处发生变化,就会发生这种情况。 【参考方案1】:

既然您说您使用的是自定义字体,那么根据之前的经验,我最好的猜测是,您看到的问题的根本原因在于自定义字体本身的某处内部。每当客户给我自定义字体时,90% 的情况下,实际字体指标都会出现“错误”(由 Apple 的内部字体渲染子系统解释,即使它可能在其他地方正确渲染)。

好消息是这是可以修复的,但它需要使用新的指标重建字体,这通常是一个试验/错误事件。您可能还需要检查您拥有的字体许可证是否允许这样的事情(如果它甚至很重要)。

话虽如此,这些是我在开始一个新项目时为这个确切场景保留的一些问题的资源:

这里有一个与您类似的问题,假设这自定义字体问题:“Custom UIFont baseline shifted”。这个问题在 UIButton "UIButton custom font vertical alignment" 中处理了这个问题,但是这两个问题最终都得到了这个问题 "Custom installed font not displayed correctly in UILabel" 的答案。

我现在有一个用于自定义字体的个人测试平台应用程序,每当我第一次获得自定义字体时我都会使用它。这允许我为每次重建迭代单独测试字体,以确保它完美呈现。确保以各种字体大小甚至其他语言(是的,大量排列)测试您的更改。在使用自定义字体时,我特别遇到了泰语和中文的问题,因为它们的上升器非常靠近 UILabel 的边界框的边缘。我为自己创建的测试平台包括各种尺寸的基本 UILabel 中呈现的字体和各种尺寸的各种语言(就像我说的那样,我过去在某些语言中使用自定义字体渲染得很好罗马字符)。

如果有人对此有更好的解决方案,我很乐意听到,因为我几乎每次都遇到自定义字体的问题。这是我在开始补偿布局期间的字体渲染问题或使用单独的属性字符串调整之前将问题扼杀在萌芽状态的工作流程。我不是字体专家,我只是一个喜欢像内置字体一样渲染字体的人(尤其是在使用自动布局时)。

【讨论】:

谢谢。我很想看到你的字体测试套件开源!再次感谢。 我发现问题发生在系统字体上,所以它不是特定于自定义字体。【参考方案2】:

你可以计算行数,如果只有一行,则将lineSpacing设置为0。

但可能有更好的解决方案。

【讨论】:

这看起来很合理,我可能会从我父视图的 layoutSubviews 中实现它。 FWIW 我已经广泛使用 ios 的各种文本 API,我记得 NSParagraphStyle 在 UILabel 中的行为非常奇怪。【参考方案3】:
paragraphStyle.lineBreakMode = NSLineBreakByCharWrapping 

文本为多行时可以避免这个问题。

使用 fontName [UIFont fontWithName:@"PingFangSC-Regular" size:14] 显式设置字体,而不是使用 [UIFont systemFontOfSize:14] 可以避免文本为单行时的问题。

希望对你有帮助!

【讨论】:

最初的问题是关于UILabel 中单行文本中不需要的行间距。问题中描述的问题不会在多行文本中表现出来,所以我看不出这是如何回答原始问题的。【参考方案4】:

这是定义。 UILabel 的问题。它适用于自定义字体和系统字体。

如果你可以使用UITextView,那就去吧。 UITextView 在单行或多行文本行间距方面没有问题,并且行为正确(单行 = 无行间距)。 这样您还可以避免创建自定义行数 func/ext。

【讨论】:

【参考方案5】:

是的,无论标签中有多少行,都会应用lineSpacing。如果您使用自动布局,您可以通过将标签的 baseline 约束到其父视图或兄弟视图(视情况而定)来解决此问题,而不是将标签的顶部边缘与父视图或兄弟视图的顶部对齐。 (但是,这假设您的标签的背景颜色与其父视图的颜色相同;否则,您会看到额外的行距出现在背景颜色中。

您可以做的另一件事(这可能是更可取的,现在我想了想)是设置paragraphSpacing 属性为0。这应该否定标签中最后一行的lineSpacing,无论您有多少行。

【讨论】:

paragraphSpacing 没有效果,除非有多个文本段落,这是有道理的(不幸的是)。而且我不确定您对基线对齐有何看法? 我现在明白了——你建议我使用标签的基线而不是底部,因为它在两种情况下都是一致的。不幸的是,这在实践中没有任何区别。 只是仔细检查了一遍——事实上,当与标签的基线对齐时,当使用多行时,视图实际上与文本重叠。 "...无论标签中有多少行,都会应用 lineSpacing。"这是不正确的。正如原始问题所示,多行文本中的最后一行后面没有空格,但单行文本后面确实有空格。对我来说,这似乎是 UILabelNSMutableParagraphStyle 中的一个错误。我看不出这是如何预期的行为。

以上是关于带有单行文本的 UILabel 的行间距的主要内容,如果未能解决你的问题,请参考以下文章

带有段落样式行间距的 UILabel

iOS--UILabel设置行距和字间距,并根据文本计算高度

IOS开发调整UILabel的行间距

UILabel 调整行间距

UILabel 调整行间距

(转)iOS学习——UIlabel设置行间距和字间距