UILabel 子类 - 尽管标签高度正确,但文本在底部被截断
Posted
技术标签:
【中文标题】UILabel 子类 - 尽管标签高度正确,但文本在底部被截断【英文标题】:UILabel subclass - text cut off in bottom despite label being correct height 【发布时间】:2016-07-10 15:17:03 【问题描述】:UILabel 子类在底部截断文本时遇到问题。标签的高度适合文本,底部还有一些空间,但文本仍然被截断。
红色条纹是添加到标签层的边框。
我对标签进行子类化以添加边缘插图。
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))
但是,在这种特殊情况下,插图为零。
【问题讨论】:
由于标签的高度小于字体大小或减小字体大小,尝试增加UILabel高度。 如您所见,文字高度低于标签高度。另外,如果我使用常规标签而不是这个子类,文本不会被截断。 @mag_zbc 您使用的是哪种自定义字体。 对我有用的是允许包含视图变得更高,如Height >=
【参考方案1】:
原来问题出在
self.lineBreakMode = .ByClipping
改成
self.lineBreakMode = .ByCharWrapping
解决了问题
【讨论】:
【参考方案2】:同时为标签提供 topAnchor 和 centerYAnchor 时发生在我身上。 只留下一个锚就解决了这个问题。
【讨论】:
【参考方案3】:其他答案对我没有帮助,但所做的是将标签的高度限制为所需的任何高度,如下所示:
let unconstrainedSize = CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude)
label.heightAnchor.constraint(equalToConstant: label.sizeThatFits(unconstrainedSize).height).isActive = true
此外,如果标签的 text
字段为 nil
或等于 ""
,sizeThatFits(_:)
将返回 0 by 0
大小
【讨论】:
【参考方案4】:我的问题是标签的(垂直)内容抗压缩优先级不够高;将其设置为所需的 (1000) 即可修复它。
看起来其他非 OP 答案可能是解决同一潜在问题的某种解决方法。
【讨论】:
【参考方案5】:我也遇到过这个问题,但想避免添加高度限制。我已经创建了一个UILabel
子类,它允许我添加内容插入(但为了将tableHeaderView
直接设置为标签,而不必将其包含在另一个视图中)。使用该类,我可以设置底部插图来解决字体裁剪问题。
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
)
【讨论】:
我怀疑某些字体存在配置问题,导致此错误。非常好的解决方案。 这不适用于很长的文本。最后两个字总是被删掉。 UILabel 似乎无论任何人尝试什么都会被切断,这令人抓狂。解决方案是直接切换到 textView ——希望我很久以前就这样做了,因为 UILabel 是一个完整而彻底的 Apple 噩梦,包裹在龙卷风中。【参考方案6】:Helvetica Neue Condensed Bold 字体我也遇到了同样的问题。将标签的 Baseline 属性从 Align Baselines 更改为 Align Centers 对我有用.您可以通过选择标签在情节提要中轻松更改此设置。
【讨论】:
这里也一样。使用 Helvetica Neue Condensed Bold 作为文本标签。设置属性有帮助。 如果不起作用,请尝试“.none”。我提交了一个答案,解释了这种略有不同的方法以及为什么“.alignCenters”解决方案只能在某些时候起作用。【参考方案7】:TL'DR
您要查找的属性可能是UILabel 的baselineAdjustment
。
需要它是因为旧的 UILabel 的已知错误。试试看:
label.baselineAdjustment = .none
也可以通过界面生成器进行更改。此属性可以在 UILabel 的属性检查器 下找到,名称为 "Baseline"。
说明
这是一个错误
有一些讨论,如this one,关于 UILabel 的文本边界框上的一个错误。在我们的案例中我们观察到的是这个错误的某个版本。当我们通过 AutoShrink .minimumFontScale
或 .minimumFontSize
收缩文本时,边界框的高度似乎会增加。
因此,边界框变得比行高和 UILabel 高度的可见部分更大。也就是说,将baselineAdjustment
属性设置为默认状态.alignBaselines
,文本与裁剪后的底部对齐,我们可以观察到线剪裁。
理解这种行为对于解释为什么 set .alignCenters
解决一些问题而不解决其他问题至关重要。只是在较大的边界框上居中文本仍然可以剪辑它。
解决方案
所以最好的办法是设置
label.baselineAdjustment = .none
.none
案例的文档说:
相对于边界框的左上角调整文本。这 是默认调整。
由于绑定框原点与标签的框架匹配,它应该可以解决启用AutoShrink
的单行标签的任何问题。
也可以通过界面生成器进行更改。此属性可以在 UILabel 的属性检查器 下找到,名称为 "Baseline"。
文档
你可以在这里阅读更多关于 UILabel 的 baselineAdjustment
官方documentation。
【讨论】:
您的解释有道理,但不适用于我的情况。我不知道为什么。【参考方案8】:我有一个垂直的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 子类 - 尽管标签高度正确,但文本在底部被截断的主要内容,如果未能解决你的问题,请参考以下文章