UILabel 子类 - 尽管标签高度正确,但文本在底部被截断
UILabel subclass - text cut off in bottom despite label being correct height
我的 UILabel 子类在底部截断文本时遇到问题。标签的高度适合文本,底部还有一些 space,但文本仍被截断。
红色条纹是添加到标签层的边框。
我将标签子类化以添加边缘插入。
override func sizeThatFits(size: CGSize) -> CGSize {
var size = super.sizeThatFits(size)
size.width += insets.left + insets.right
size.height += insets.top + insets.bottom
return size
}
override func drawTextInRect(rect: CGRect) {
super.drawTextInRect(UIEdgeInsetsInsetRect(rect, insets))
}
但是,在这种特殊情况下,插入为零。
原来问题出在
self.lineBreakMode = .ByClipping
改为
self.lineBreakMode = .ByCharWrapping
解决了问题
同时为标签提供 topAnchor 和 centerYAnchor 时发生在我身上。
只留下一个锚点就解决了这个问题。
其他答案对我没有帮助,但是将标签的高度限制在它需要的任何高度,就像这样:
let unconstrainedSize = CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude)
label.heightAnchor.constraint(equalToConstant: label.sizeThatFits(unconstrainedSize).height).isActive = true
此外,如果标签的 text
字段是 nil
或等于 ""
[=,sizeThatFits(_:)
将 return 尺寸 0 by 0
16=]
我的问题是标签的(垂直)内容抗压缩优先级不够高;将其设置为必需 (1000) 修复它。
看起来其他非 OP 答案可能是针对同一潜在问题的某种解决方法。
我 运行 也参与其中,但想避免添加高度限制。我已经创建了一个 UILabel
subclass,它允许我添加内容插图(但目的是将 tableHeaderView
直接设置为标签,而不必将其包含在另一个视图中)。使用 class 我可以设置底部插图来解决字体剪裁问题。
import UIKit
@IBDesignable class InsetLabel: UILabel {
@IBInspectable var topInset: CGFloat = 16
@IBInspectable var bottomInset: CGFloat = 16
@IBInspectable var leftInset: CGFloat = 16
@IBInspectable var rightInset: CGFloat = 16
var insets: UIEdgeInsets {
get {
return UIEdgeInsets(
top: topInset,
left: leftInset,
bottom: bottomInset,
right: rightInset
)
}
}
override func drawText(in rect: CGRect) {
super.drawText(in: rect.inset(by: insets))
}
override var intrinsicContentSize: CGSize {
return addInsetsTo(size: super.intrinsicContentSize)
}
override func sizeThatFits(_ size: CGSize) -> CGSize {
return addInsetsTo(size: super.sizeThatFits(size))
}
func addInsetsTo(size: CGSize) -> CGSize {
return CGSize(
width: size.width + leftInset + rightInset,
height: size.height + topInset + bottomInset
)
}
}
这可以简化为字体剪辑:
import UIKit
class FontFittingLabel: UILabel {
var inset: CGFloat = 16 // Adjust this
override func drawText(in rect: CGRect) {
super.drawText(in: rect.inset(by: UIEdgeInsets(
top: 0,
left: 0,
bottom: inset,
right: 0
)))
}
override var intrinsicContentSize: CGSize {
let size = super.intrinsicContentSize
return CGSize(
width: size.width,
height: size.height + inset
)
}
}
我在使用 Helvetica Neue Condensed Bold 字体时遇到了同样的问题。将标签的 Baseline 属性 从 Align Baselines 更改为 Align Centers 对我有用。您可以通过选择标签在情节提要中轻松更改此设置。
TL'DR
你要找的属性可能是UILabel的baselineAdjustment
.
由于旧的 UILabel 的已知错误,因此需要它。试一试:
label.baselineAdjustment = .none
也可以通过 interface builder 进行更改。这个 属性 可以在 UILabel 的属性检查器 下找到,名称为 "Baseline".
说明
这是一个错误
像 这样的讨论是关于 UILabel 的文本边界框上的错误。在我们的案例中,我们在这里观察到的是这个错误的某个版本。当我们通过 AutoShrink .minimumFontScale
或 .minimumFontSize
.
缩小文本 时,看起来 边界框的高度会增加
因此,边界框变得大于行高和 UILabel 高度的可见部分。也就是说,将 baselineAdjustment
属性 设置为默认状态 .alignBaselines
,文本与裁剪后的底部对齐,我们可以观察到线条剪裁。
理解这种行为对于解释为什么 set .alignCenters
解决了一些问题而不是其他问题至关重要。只需将较大边界框上的文本居中,仍然可以将其剪裁掉。
解决方案
所以最好的方法是设置
label.baselineAdjustment = .none
.none
案例的文档说:
Adjust text relative to the top-left corner of the bounding box. This
is the default adjustment.
由于绑定框原点与标签的框架相匹配,它应该可以解决启用 AutoShrink
的单行标签的任何问题。
也可以通过 interface builder 进行更改。这个 属性 可以在 UILabel 的属性检查器 下找到,名称为 "Baseline".
文档
您可以在此处阅读有关 UILabel 的 baselineAdjustment
官方 documentation 的更多信息。
我有一个垂直的 UIStackView
,底部有一个 UILabel
。此 UILabel
会切断基线以下的字母(q
、g
、y
等),但仅当嵌套在水平 UIStackView
内时.解决方法是将 .lastBaseline
对齐修饰符添加到外部堆栈视图。
lazy var stackView: UIStackView = {
let stackView = UIStackView(arrangedSubviews: [
aVerticalStackWithUILabelAtBottom, // <-- bottom UILabel was cutoff
UIView(),
someOtherView
])
stackView.axis = .horizontal
stackView.spacing = Spacing.one
stackView.alignment = .lastBaseline // <-- BOOM fixed it
stackView.isUserInteractionEnabled = true
return stackView
}()
我的 UILabel 子类在底部截断文本时遇到问题。标签的高度适合文本,底部还有一些 space,但文本仍被截断。
红色条纹是添加到标签层的边框。
我将标签子类化以添加边缘插入。
override func sizeThatFits(size: CGSize) -> CGSize {
var size = super.sizeThatFits(size)
size.width += insets.left + insets.right
size.height += insets.top + insets.bottom
return size
}
override func drawTextInRect(rect: CGRect) {
super.drawTextInRect(UIEdgeInsetsInsetRect(rect, insets))
}
但是,在这种特殊情况下,插入为零。
原来问题出在
self.lineBreakMode = .ByClipping
改为
self.lineBreakMode = .ByCharWrapping
解决了问题
同时为标签提供 topAnchor 和 centerYAnchor 时发生在我身上。 只留下一个锚点就解决了这个问题。
其他答案对我没有帮助,但是将标签的高度限制在它需要的任何高度,就像这样:
let unconstrainedSize = CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude)
label.heightAnchor.constraint(equalToConstant: label.sizeThatFits(unconstrainedSize).height).isActive = true
此外,如果标签的 text
字段是 nil
或等于 ""
[=,sizeThatFits(_:)
将 return 尺寸 0 by 0
16=]
我的问题是标签的(垂直)内容抗压缩优先级不够高;将其设置为必需 (1000) 修复它。
看起来其他非 OP 答案可能是针对同一潜在问题的某种解决方法。
我 运行 也参与其中,但想避免添加高度限制。我已经创建了一个 UILabel
subclass,它允许我添加内容插图(但目的是将 tableHeaderView
直接设置为标签,而不必将其包含在另一个视图中)。使用 class 我可以设置底部插图来解决字体剪裁问题。
import UIKit
@IBDesignable class InsetLabel: UILabel {
@IBInspectable var topInset: CGFloat = 16
@IBInspectable var bottomInset: CGFloat = 16
@IBInspectable var leftInset: CGFloat = 16
@IBInspectable var rightInset: CGFloat = 16
var insets: UIEdgeInsets {
get {
return UIEdgeInsets(
top: topInset,
left: leftInset,
bottom: bottomInset,
right: rightInset
)
}
}
override func drawText(in rect: CGRect) {
super.drawText(in: rect.inset(by: insets))
}
override var intrinsicContentSize: CGSize {
return addInsetsTo(size: super.intrinsicContentSize)
}
override func sizeThatFits(_ size: CGSize) -> CGSize {
return addInsetsTo(size: super.sizeThatFits(size))
}
func addInsetsTo(size: CGSize) -> CGSize {
return CGSize(
width: size.width + leftInset + rightInset,
height: size.height + topInset + bottomInset
)
}
}
这可以简化为字体剪辑:
import UIKit
class FontFittingLabel: UILabel {
var inset: CGFloat = 16 // Adjust this
override func drawText(in rect: CGRect) {
super.drawText(in: rect.inset(by: UIEdgeInsets(
top: 0,
left: 0,
bottom: inset,
right: 0
)))
}
override var intrinsicContentSize: CGSize {
let size = super.intrinsicContentSize
return CGSize(
width: size.width,
height: size.height + inset
)
}
}
我在使用 Helvetica Neue Condensed Bold 字体时遇到了同样的问题。将标签的 Baseline 属性 从 Align Baselines 更改为 Align Centers 对我有用。您可以通过选择标签在情节提要中轻松更改此设置。
TL'DR
你要找的属性可能是UILabel的baselineAdjustment
.
由于旧的 UILabel 的已知错误,因此需要它。试一试:
label.baselineAdjustment = .none
也可以通过 interface builder 进行更改。这个 属性 可以在 UILabel 的属性检查器 下找到,名称为 "Baseline".
说明
这是一个错误
像 .minimumFontScale
或 .minimumFontSize
.
因此,边界框变得大于行高和 UILabel 高度的可见部分。也就是说,将 baselineAdjustment
属性 设置为默认状态 .alignBaselines
,文本与裁剪后的底部对齐,我们可以观察到线条剪裁。
理解这种行为对于解释为什么 set .alignCenters
解决了一些问题而不是其他问题至关重要。只需将较大边界框上的文本居中,仍然可以将其剪裁掉。
解决方案
所以最好的方法是设置
label.baselineAdjustment = .none
.none
案例的文档说:
Adjust text relative to the top-left corner of the bounding box. This is the default adjustment.
由于绑定框原点与标签的框架相匹配,它应该可以解决启用 AutoShrink
的单行标签的任何问题。
也可以通过 interface builder 进行更改。这个 属性 可以在 UILabel 的属性检查器 下找到,名称为 "Baseline".
文档
您可以在此处阅读有关 UILabel 的 baselineAdjustment
官方 documentation 的更多信息。
我有一个垂直的 UIStackView
,底部有一个 UILabel
。此 UILabel
会切断基线以下的字母(q
、g
、y
等),但仅当嵌套在水平 UIStackView
内时.解决方法是将 .lastBaseline
对齐修饰符添加到外部堆栈视图。
lazy var stackView: UIStackView = {
let stackView = UIStackView(arrangedSubviews: [
aVerticalStackWithUILabelAtBottom, // <-- bottom UILabel was cutoff
UIView(),
someOtherView
])
stackView.axis = .horizontal
stackView.spacing = Spacing.one
stackView.alignment = .lastBaseline // <-- BOOM fixed it
stackView.isUserInteractionEnabled = true
return stackView
}()