将多行标签(换行符设置为自动换行)放入堆栈视图时,标签会立即丢失换行符并在一行中显示标签文本。
为什么会发生这种情况以及如何在堆栈视图中保留多行标签?
将多行标签(换行符设置为自动换行)放入堆栈视图时,标签会立即丢失换行符并在一行中显示标签文本。
为什么会发生这种情况以及如何在堆栈视图中保留多行标签?
正确答案在这里:
https ://stackoverflow.com/a/43110590/566360
UILabel
内部UIView
(编辑器 -> 嵌入 -> 视图)UILabel
使用约束来适应UIView
(例如,尾随空间、顶部空间和前导空间到超级视图约束)将UIStackView
拉伸UIView
以适当地适合,UIView
并将限制UILabel
到多行。
对于以 aUILabel
作为其视图之一的水平堆栈视图,首先在 Interface Builder 中设置label.numberOfLines = 0
. 这应该允许标签有超过 1 行。当堆栈视图有stackView.alignment = .fill
. 要使其工作,只需设置stackView.alignment = .center
. 标签现在可以扩展到UIStackView
.
苹果文档说
对于除填充对齐之外的所有对齐方式,堆栈视图在计算垂直于堆栈轴的大小时使用每个排列视图的固有ContentSize 属性
注意除此处以外的词。使用.fill
时,水平UIStackView
不会使用排列的子视图的大小垂直调整自身大小。
将 preferredMaxLayoutWidth 设置为 UILabel 对我有用
self.myLabel.preferredMaxLayoutWidth = self.bounds.size.width;
在尝试了上述所有建议后,我发现 UIStackView 不需要更改属性。我只是将 UILabels 的属性更改如下(标签已添加到垂直堆栈视图中):
斯威夫特 4 示例:
[titleLabel, subtitleLabel].forEach(){
$0.numberOfLines = 0
$0.lineBreakMode = .byWordWrapping
$0.setContentCompressionResistancePriority(UILayoutPriority.required, for: .vertical)
}
iOS 9+
[textLabel sizeToFit]
设置 UILabel 的文本后调用。
sizeToFit 将使用preferredMaxWidth 重新布局多行标签。标签将调整 stackView 的大小,这将调整单元格的大小。除了将堆栈视图固定到内容视图之外,不需要其他约束。
对我来说,魔术是将 a 设置widthAnchor
为UIStackView
.
设置leadingAnchor
并trailingAnchor
不起作用,但设置centerXAnchor
并使widthAnchor
UILabel 正确显示。
UIStackView
的多行组成的垂直的完整示例。UILabel
标签根据 stackview 的宽度换行,stackview 的高度基于标签的换行高度。(使用这种方法,您无需将标签嵌入UIView
.)(Swift 5,iOS 12.2)
// A vertical stackview with multiline labels and automatic height.
class ThreeLabelStackView: UIStackView {
let label1 = UILabel()
let label2 = UILabel()
let label3 = UILabel()
init() {
super.init(frame: .zero)
self.translatesAutoresizingMaskIntoConstraints = false
self.axis = .vertical
self.distribution = .fill
self.alignment = .fill
label1.numberOfLines = 0
label2.numberOfLines = 0
label3.numberOfLines = 0
label1.lineBreakMode = .byWordWrapping
label2.lineBreakMode = .byWordWrapping
label3.lineBreakMode = .byWordWrapping
self.addArrangedSubview(label1)
self.addArrangedSubview(label2)
self.addArrangedSubview(label3)
// (Add some test data, a little spacing, and the background color
// make the labels easier to see visually.)
self.spacing = 1
label1.backgroundColor = .orange
label2.backgroundColor = .orange
label3.backgroundColor = .orange
label1.text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi."
label2.text = "Hello darkness my old friend..."
label3.text = "When I wrote the following pages, or rather the bulk of them, I lived alone, in the woods, a mile from any neighbor, in a house which I had built myself, on the shore of Walden Pond, in Concord, Massachusetts, and earned my living by the labor of my hands only."
}
required init(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
}
ViewController
这是一个使用它的示例。
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let myLabelStackView = ThreeLabelStackView()
self.view.addSubview(myLabelStackView)
// Set stackview width to its superview.
let widthConstraint = NSLayoutConstraint(item: myLabelStackView, attribute: NSLayoutConstraint.Attribute.width, relatedBy: NSLayoutConstraint.Relation.equal, toItem: self.view, attribute: NSLayoutConstraint.Attribute.width, multiplier: 1, constant: 0)
self.view.addConstraints([widthConstraint])
}
}
添加UIStackView
属性,
stackView.alignment = .fill
stackView.distribution = .fillProportionally
stackView.spacing = 8.0
stackView.axis = .horizontal
UIView
而不是在里面添加不需要的标签。如果您在里面使用,UITableViewCell
请在旋转时重新加载数据。
2020 年 11 月 26 日,Xcode 12.2,iOS 14.2。以下适用于我的垂直堆栈视图。它适用于所有设备和模拟器。我使用情节提要,所有这些值都在情节提要中设置。
UIL标签
行数:0
UIStackView
对齐方式:填充
分布:按比例填充
UILabel 嵌入在视图中,并固定到 UIView 的各个方面。
以下是多行标签的 Playground 实现,其中包含一个换行符UIStackView
。它不需要在UILabel
内部嵌入任何东西,并且已经使用 Xcode 9.2 和 Swift 4 进行了测试。希望对您有所帮助。
import UIKit
import PlaygroundSupport
let containerView = UIView()
containerView.frame = CGRect.init(x: 0, y: 0, width: 400, height: 500)
containerView.backgroundColor = UIColor.white
var label = UILabel.init()
label.textColor = .black
label.numberOfLines = 0
label.translatesAutoresizingMaskIntoConstraints = false
label.text = "This is an example of sample text that goes on for a long time. This is an example of sample text that goes on for a long time."
let stackView = UIStackView.init(arrangedSubviews: [label])
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.axis = .vertical
stackView.distribution = .fill
stackView.alignment = .fill
containerView.addSubview(stackView)
stackView.centerXAnchor.constraint(equalTo: containerView.centerXAnchor).isActive = true
stackView.centerYAnchor.constraint(equalTo: containerView.centerYAnchor).isActive = true
stackView.widthAnchor.constraint(equalTo: containerView.widthAnchor).isActive = true
stackView.heightAnchor.constraint(equalTo: containerView.heightAnchor).isActive = true
PlaygroundPage.current.liveView = containerView
系统布局应该找出原点、宽度和高度来绘制它的子视图,在这种情况下,你所有的子视图都具有相同的优先级,这点会产生冲突,布局系统不知道视图之间的依赖关系,哪个先绘制,第二个等等
设置堆栈子视图压缩将解决多行问题,具体取决于您的堆栈视图是水平的还是垂直的以及您希望哪一个成为多行。 stackOtherSubviews .setContentCompressionResistancePriority(.defaultHight, for: .horizontal)
lblTitle.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
在尝试了此页面上的大多数答案之后,我的解决方案是根本不使用 UIStackView。
我意识到我并不真正需要它,只是出于习惯使用它,并且可以使用 UIView 完成同样的事情。
就我而言,我遵循了之前的建议,但我的文本仍然被截断为一行,尽管只是在横向中。原来,我\0
在标签的文本中发现了一个不可见的空字符,这是罪魁祸首。它一定是在我插入的破折号符号旁边引入的。要查看您的情况是否也发生这种情况,请使用 View Debugger 选择您的标签并检查其文本。
什么对我有用!
stackview:对齐:填充,分布:填充,约束比例宽度到superview ex。0.8,
标签:中心,线 = 0
对于仍然无法使其工作的任何人。尝试在该 UILabel 上设置具有最小字体比例的 Autoshrink。
这几乎就像@Andy's Answer,但你可以添加你UILabel
的额外UIStackview
,垂直为我工作。
对我来说,问题是堆栈视图的高度太短了。标签和堆栈视图已正确设置以允许标签具有多行,但标签是堆栈视图用来使其高度足够小的内容压缩的第一个受害者。
对于那些使用情节提要或XIB文件尝试将 UILabel 嵌入到水平堆栈视图中的人,请勿在创建堆栈视图之前将约束添加到您计划放入堆栈视图的任何内容。这将导致错误和/或无法换行。
相反,除了Andy 和 pmb提出的建议之外,还要这样做。
UILabel
个UIView
.UILabel
行 = 0。不知道为什么这种操作顺序会有所不同,但确实如此。
您可以在您的标签属性文本中使用“\n”和相关的 numberOfLines