UIStackView中的多行标签

问题描述 投票:106回答:16

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

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

ios uikit uilabel xcode7 uistackview
16个回答
161
投票

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

  1. UILabel嵌入UIView(编辑器 - >嵌入 - >视图) 使用约束使UILabel适合UIView(例如,尾随空间,顶部空间和前导空间到superview约束)

UIStackView将伸展UIView以适应,而UIViewUILabel限制为多行。


2
投票

Here's a full example of a vertical UIStackView made up of multiline UILabels with automatic height.

标签根据stackview的宽度进行换行,stackview的高度基于标签的包裹高度。 (使用这种方法,您不需要在UIView中嵌入标签。)(Swift 5,iOS 12.2)

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])
    }
}

1
投票

系统布局应该弄清楚它的子视图的原点,宽度和高度,在这种情况下你的所有子视图都有相同的优先级,那点使冲突,布局系统不知道视图之间的依赖关系,哪一个绘制第一,第二等等

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


1
投票

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

Swift 4示例:

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

0
投票

在我的情况下,我遵循了之前的建议,但我的文本仍然被截断为单行但仅在横向上。事实证明,我在标签的文本中发现了一个看不见的\0 null字符,这是罪魁祸首。它必须与我插入的em破折号符号一起引入。要查看是否还发生了这种情况,请使用View Debugger选择标签并检查其文本。


0
投票

Xcode 9.2:

只需将行数设置为0.设置此项后,故事板看起来很奇怪。不要担心运行该项目。运行时,所有内容都会根据故事板设置调整大小。我认为它是故事板中的那种错误。 enter image description here

提示:在最后设置“衬里数量为0”。要编辑其他视图时重置它,编辑后设置为0。

enter image description here


0
投票

什么对我有用!

stackview:alignment:fill,distribution:fill,约束比例宽度到superview ex。 0.8,

label:center和lines = 0


0
投票

对于任何仍然无法使其工作的人。尝试在UILabel上使用最小字体缩放设置自动收缩。

Screenshot UILabel Autoshrink settings


0
投票

它几乎就像@Andy的答案,但你可以在额外的UILabel中添加你的UIStackview,垂直为我工作。


87
投票

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

Apple documentation

对于除填充对齐之外的所有对齐,堆栈视图在计算垂直于堆栈轴的大小时使用每个已排列视图的内在内容大小属性

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


41
投票
  • 首先将标签行数设置为0
  • 除非你给它一个固定的宽度,否则堆栈视图仍然不会增长到multiLine。当我们修正它的宽度时,它会在达到该宽度时断开到多线,如图所示:

screen recording

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

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


11
投票

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

enter image description here


8
投票

将preferredMaxLayoutWidth设置为UILabel对我有用

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

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

3
投票

iOS 9+

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

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


2
投票

添加UIStackView属性,

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

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


2
投票

对我来说,神奇的诀窍是将widthAnchor设置为UIStackView

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

© www.soinside.com 2019 - 2024. All rights reserved.