将多行标签(将换行符设置为Word Wrap)放入堆栈视图时,标签会立即丢失换行符并在一行中显示标签文本。
为什么会发生这种情况?如何在堆栈视图中保留多行标签?
正确答案在这里:https://stackoverflow.com/a/43110590/566360
UILabel
嵌入UIView
(编辑器 - >嵌入 - >视图)
使用约束使UILabel
适合UIView
(例如,尾随空间,顶部空间和前导空间到superview约束)UIStackView
将伸展UIView
以适应,而UIView
将UILabel
限制为多行。
UIStackView
made up of multiline UILabel
s with automatic height.标签根据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])
}
}
系统布局应该弄清楚它的子视图的原点,宽度和高度,在这种情况下你的所有子视图都有相同的优先级,那点使冲突,布局系统不知道视图之间的依赖关系,哪一个绘制第一,第二等等
设置堆栈子视图压缩将解决多行问题,具体取决于您的堆栈视图是水平还是垂直,哪一个要成为多行。 stackOtherSubviews .setContentCompressionResistancePriority(.defaultHight, for: .horizontal)
lblTitle.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
在尝试了上述所有建议后,我发现UIStackView不需要更改属性。我只需更改UILabel的属性如下(标签已添加到垂直堆栈视图):
Swift 4示例:
[titleLabel, subtitleLabel].forEach(){
$0.numberOfLines = 0
$0.lineBreakMode = .byWordWrapping
$0.setContentCompressionResistancePriority(UILayoutPriority.required, for: .vertical)
}
在我的情况下,我遵循了之前的建议,但我的文本仍然被截断为单行但仅在横向上。事实证明,我在标签的文本中发现了一个看不见的\0
null字符,这是罪魁祸首。它必须与我插入的em破折号符号一起引入。要查看是否还发生了这种情况,请使用View Debugger选择标签并检查其文本。
什么对我有用!
stackview:alignment:fill,distribution:fill,约束比例宽度到superview ex。 0.8,
label:center和lines = 0
对于任何仍然无法使其工作的人。尝试在UILabel上使用最小字体缩放设置自动收缩。
它几乎就像@Andy的答案,但你可以在额外的UILabel
中添加你的UIStackview
,垂直为我工作。
对于以UILabel
作为其视图之一的水平堆栈视图,在Interface Builder中首先设置label.numberOfLines = 0
。这应该允许标签有多于1行。当堆栈视图有stackView.alignment = .fill
时,这最初无法为我工作。为了使它工作简单设置stackView.alignment = .center
。标签现在可以扩展到UIStackView
内的多行。
对于除填充对齐之外的所有对齐,堆栈视图在计算垂直于堆栈轴的大小时使用每个已排列视图的内在内容大小属性
注意这里除了这个词。当使用.fill
时,水平UIStackView
不会使用排列的子视图大小垂直调整自身大小。
将preferredMaxLayoutWidth设置为UILabel对我有用
self.myLabel.preferredMaxLayoutWidth = self.bounds.size.width;
以下是多线标签的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
iOS 9+
在设置UILabel的文本后调用[textLabel sizeToFit]
。
sizeToFit将使用preferredMaxWidth重新布局多行标签。标签将调整stackView的大小,这将调整单元格的大小。除了将堆栈视图固定到内容视图之外,不需要额外的约束。
添加UIStackView
属性,
stackView.alignment = .fill
stackView.distribution = .fillProportionally
stackView.spacing = 8.0
stackView.axis = .horizontal
而不是在UIView
内添加标签,这是不需要的。如果你在UITableViewCell
内使用,请在旋转时重新加载数据。
对我来说,神奇的诀窍是将widthAnchor
设置为UIStackView
。
设置leadingAnchor
和trailingAnchor
不起作用,但设置centerXAnchor
和widthAnchor
使UILabel显示正确。