188

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

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

4

22 回答 22

254

正确答案在这里:
https ://stackoverflow.com/a/43110590/566360


  1. 嵌入UILabel内部UIView(编辑器 -> 嵌入 -> 视图)
  2. UILabel使用约束来适应UIView(例如,尾随空间、顶部空间和前导空间到超级视图约束)

UIStackView拉伸UIView以适当地适合,UIView并将限制UILabel到多行。

于 2016-07-10T17:12:03.480 回答
210

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

苹果文档

对于除填充对齐之外的所有对齐方式,堆栈视图在计算垂直于堆栈轴的大小时使用每个排列视图的固有​Content​Size 属性

注意此处以外的词。使用.fill时,水平UIStackView不会使用排列的子视图的大小垂直调整自身大小。

于 2017-03-30T06:53:17.793 回答
44
  • 首先将标签行数设置为0
  • multiLine除非你给它一个固定的宽度,否则堆栈视图仍然不会增长。当我们固定它的宽度时,当达到该宽度时它会中断为多行,如下所示:

录屏

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

希望这可以解决您的问题。

于 2015-12-23T06:54:12.467 回答
34

将 preferredMaxLayoutWidth 设置为 UILabel 对我有用

self.myLabel.preferredMaxLayoutWidth = self.bounds.size.width;
于 2018-06-08T08:32:07.343 回答
29

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

斯威夫特 4 示例:

[titleLabel, subtitleLabel].forEach(){
    $0.numberOfLines = 0
    $0.lineBreakMode = .byWordWrapping
    $0.setContentCompressionResistancePriority(UILayoutPriority.required, for: .vertical)
}
于 2019-01-24T14:43:34.740 回答
14

只需在标签的属性检查器中将行数设置为 0。它会为你工作。

在此处输入图像描述

于 2015-12-21T06:21:47.167 回答
5

iOS 9+

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

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

于 2016-07-24T16:32:27.150 回答
5

对我来说,魔术是将 a 设置widthAnchorUIStackView.

设置leadingAnchortrailingAnchor不起作用,但设置centerXAnchor并使widthAnchorUILabel 正确显示。

于 2018-06-26T17:34:44.657 回答
5

这是一个由具有自动高度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])
    }
}
于 2019-06-22T22:31:15.973 回答
4

添加UIStackView属性,

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

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

于 2017-11-30T07:30:14.920 回答
4

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

UIL标签

行数:0

UIStackView

对齐方式:填充

分布:按比例填充

UILabel 嵌入在视图中,并固定到 UIView 的各个方面。

于 2020-11-25T17:54:21.550 回答
3

以下是多行标签的 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
于 2018-03-28T20:29:40.770 回答
0

系统布局应该找出原点、宽度和高度来绘制它的子视图,在这种情况下,你所有的子视图都具有相同的优先级,这点会产生冲突,布局系统不知道视图之间的依赖关系,哪个先绘制,第二个等等

设置堆栈子视图压缩将解决多行问题,具体取决于您的堆栈视图是水平的还是垂直的以及您希望哪一个成为多行。 stackOtherSubviews .setContentCompressionResistancePriority(.defaultHight, for: .horizontal) lblTitle.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)

于 2018-08-27T09:41:45.883 回答
0

在尝试了此页面上的大多数答案之后,我的解决方案是根本不使用 UIStackView。

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

于 2021-03-18T13:33:42.243 回答
-1

就我而言,我遵循了之前的建议,但我的文本仍然被截断为一行,尽管只是在横向中。原来,我\0在标签的文本中发现了一个不可见的空字符,这是罪魁祸首。它一定是在我插入的破折号符号旁边引入的。要查看您的情况是否也发生这种情况,请使用 View Debugger 选择您的标签并检查其文本。

于 2017-08-13T06:23:47.803 回答
-1

Xcode 9.2:

只需将行数设置为 0。设置后情节提要看起来很奇怪。不用担心运行项目。运行时,所有内容都会根据您的故事板设置调整大小。我认为这是情节提要中的一种错误。 在此处输入图像描述

Tips : 最后设置"number of liner to 0"。当您想编辑其他视图时重置它并在编辑后设置为 0。

在此处输入图像描述

于 2018-09-07T06:04:46.783 回答
-1

什么对我有用!

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

标签:中心,线 = 0

于 2018-10-02T09:42:49.333 回答
-1

对于仍然无法使其工作的任何人。尝试在该 UILabel 上设置具有最小字体比例的 Autoshrink。

屏幕截图 UILabel 自动收缩设置

于 2019-02-11T18:22:32.297 回答
-1

这几乎就像@Andy's Answer,但你可以添加你UILabel的额外UIStackview,垂直为我工作。

于 2019-08-16T00:14:16.680 回答
-1

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

于 2019-10-31T13:34:06.743 回答
-1

对于那些使用情节提要或XIB文件尝试将 UILabel 嵌入到水平堆栈视图中的人,请勿在创建堆栈视图之前将约束添加到您计划放入堆栈视图的任何内容。这将导致错误和/或无法换行。

相反,除了Andy 和 pmb提出的建议之外,还要这样做。

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

不知道为什么这种操作顺序会有所不同,但确实如此。

于 2020-09-11T16:56:50.840 回答
-2

您可以在您的标签属性文本中使用“\n”和相关的 numberOfLines

于 2021-09-03T09:42:20.143 回答