UIStackView 中的多行标签

当将多行标签(将换行设置为自动换行)放入堆栈视图时,标签将立即失去换行,并将标签文本显示在一行中。

为什么会发生这种情况,如何在堆栈视图中保存多行标签?

105753 次浏览

只需在属性检查器中为标签设置行数为0。它会对你有用的。

enter image description here

  • 首先将标签行数设置为0
  • 堆栈视图仍然不会增长到multiLine,除非你给它一个固定的宽度。当我们固定它的宽度时,当宽度达到如下所示时,它会中断为多行:

screen recording

如果我们不给堆栈视图一个固定的宽度,那么事情就会变得模棱两可。堆栈视图将随着标签增长多长时间(如果标签值是动态的)?

希望这能解决你的问题。

正确答案是:
https://stackoverflow.com/a/43110590/566360 < / p >
  1. UILabel嵌入到UIView中(Editor -> Embed In -> View)
  2. 使用约束使UILabelUIView相匹配(例如,尾部空格、顶部空格和前导空格到父视图约束)

UIStackView将扩展UIView以适当地适应,而UIView将约束UILabel为多行。

iOS 9 +

在设置UILabel的文本后调用[textLabel sizeToFit]

sizeToFit将使用preferredMaxWidth重新布局多行标签。标签将调整stackView的大小,而stackView将调整单元格的大小。除了将堆栈视图固定到内容视图之外,不需要其他约束。

对于具有UILabel作为其视图之一的水平堆栈视图,在Interface Builder中首先设置label.numberOfLines = 0。这应该允许标签有超过一行。当堆栈视图有stackView.alignment = .fill时,这最初无法为我工作。要使它工作,只需设置stackView.alignment = .center。标签现在可以扩展为UIStackView中的多行。

苹果公司的文档表示

对于除了fill对齐之外的所有对齐方式,堆栈视图使用每种对齐方式 排列视图的固有内容大小属性计算时 垂直于堆栈轴的大小

注意这里的单词除了。当使用.fill时,水平的UIStackView不会使用排列的子视图的大小在垂直方向上调整自己的大小。

在我的情况下,我遵循了前面的建议,但我的文本仍然被截断为一行,尽管只是在横屏。事实证明,我在标签的文本中发现了一个不可见的\0空字符,这是罪魁祸首。它肯定是和我插入的em - dash符号一起被引入的。要查看这是否也发生在您的情况下,使用视图调试器选择标签并检查其文本。

添加UIStackView属性,

stackView.alignment = .fill
stackView.distribution = .fillProportionally
stackView.spacing = 8.0
stackView.axis = .horizontal

而不是在UIView中添加标签,这是不需要的。如果您正在使用UITableViewCell内部,请在旋转时重新加载数据。

下面是在UIStackView中带有换行符的多行标签的Playground实现。它不需要在任何东西中嵌入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

设置preferredmaxlayoutidth为UILabel对我有用

self.myLabel.preferredMaxLayoutWidth = self.bounds.size.width;

对我来说,神奇的技巧是将widthAnchor设置为UIStackView

设置leadingAnchortrailingAnchor将不起作用,但设置centerXAnchorwidthAnchor使UILabel正确显示。

系统布局应该计算出原点,宽度和高度来绘制它的子视图,在这种情况下,你所有的子视图都有相同的优先级,即点做出冲突,布局系统不知道视图之间的依赖关系,哪个先画,哪个后画等等

设置堆栈子视图压缩将解决多行问题,这取决于你的堆栈视图是水平的还是垂直的,以及哪一个你想成为多行。stackOtherSubviews .setContentCompressionResistancePriority(.defaultHight, for: .horizontal) lblTitle.setContentCompressionResistancePriority(.defaultLow, for: .horizontal) < / p >

Xcode 9.2:

设置行数为0。设置后故事板看起来会很奇怪。别担心,运行这个项目。在运行时,一切将根据你的故事板设置调整大小。我认为这是故事板中的bug。 enter image description here < / p >

提示:最后设置“班轮数为0”。当您想编辑其他视图时,重置它,并在编辑后将其设置为0。

enter image description here

什么对我有用!

Stackview:对齐:填充,分布:填充,约束比例宽度到superview ex. 0.8,

标签:center, lines = 0

在尝试了以上所有建议后,我发现UIStackView不需要更改属性。我只是改变UILabels的属性如下(标签已经添加到垂直堆栈视图):

Swift 4示例:

[titleLabel, subtitleLabel].forEach(){
$0.numberOfLines = 0
$0.lineBreakMode = .byWordWrapping
$0.setContentCompressionResistancePriority(UILayoutPriority.required, for: .vertical)
}

给那些还不能成功的人。尝试在该UILabel上设置最小字体规模的自动收缩。

截图UILabel自动收缩设置

下面是由具有自动高度的多行__abc1组成的垂直UIStackView的完整示例。

标签的包装基于stackview的宽度,stackview的高度基于标签的包装高度。(使用这种方法,您不需要将标签嵌入到UIView中。

enter image description here

// 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中添加你的UILabel, vertical对我来说很有用。< / p >

对我来说,问题是堆栈视图的高度太短了。标签和堆栈视图被正确地设置为允许标签有多行,但是标签是堆栈视图用来使其高度足够小的内容压缩的第一个受害者。

对于那些使用故事板XIB文件并试图在水平堆栈视图中嵌入UILabel的人来说,在创建堆栈视图之前,不要向任何计划放入堆栈视图中的东西添加约束. dll是可以使用的。这将导致错误和/或无法自动换行文本。

相反,在安迪和pmb给出的建议之外执行此操作。

  1. UIView中嵌入UILabel
  2. 设置UILabel lines = 0。
  3. 创建堆栈视图。
  4. 设置堆栈视图对齐为顶部/底部/中心。
  5. 向堆栈视图中的元素添加约束。

不知道为什么这个操作顺序会有区别,但确实有区别。

2020年11月26日,Xcode 12.2, iOS 14.2。 以下工作为我的垂直堆栈视图。它适用于所有设备和模拟器。我使用storyboard,所有这些值都在storyboard中设置

UILabel

行:0

UIStackView

对齐:填

分布:按比例填充

UILabel被嵌入到一个视图中,并固定在UIView的所有边。

在尝试了本页上的大部分答案后,我的解决方案是根本不使用UIStackView。

我意识到我并不真正需要它,只是出于习惯使用它,并且可以用UIView完成同样的事情。

您可以在标签attributedText中使用"\n"和相关的数字线

这对我很管用。(5)迅速

   let label = UILabel()
label.numberOfLines = 0
label.text = text  // text defined somewhere
label.font = font  // font defined somewhere
let height = text.height(forConstrainedWidth: stackView.width, font: font)
label.heightAnchor.constraint(equalToConstant: height).isActive = true

然后用addArrangedSubview将这个标签添加到你的stackView。