UIStackView中的多行标签


154

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

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


1
您是否将行数设置为0?
dasdom 2015年

找到答案了吗?
布伦登

Answers:


203

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


  1. 嵌入UILabel内部UIView(编辑器->嵌入->视图)
  2. 使用约束以适合UILabelUIView(例如,后空间,顶部空间,并导致空间上海华约束)

UIStackView要伸出的UIView配合不当,而UIView将限制UILabel为多行。


35
太傻了,但是行得通!谢啦 !也许有一天,苹果公司将发布其SDK中未破损的东西……
Guillaume

1
天啊!你是救世主!我已经呆了几个小时了:)记得还要在Attributes Inspector中将行设置为0,只是缺少了这一点。
苦艾酒

8
这是解决方法,正确的解决方案在这里stackoverflow.com/a/43110590/566360
vietstone

2
仅将水平对齐方式更改为居中就足够了。没有UIView必要的恶作剧。
shim

1
@Lucien这正是这个答案中所说的。但是正确的答案在这里:stackoverflow.com/a/43110590/566360
Andy

144

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

苹果的文档

对于除填充对齐方式之外的所有对齐方式,堆栈视图在计算垂直于堆栈轴的尺寸时会使用每个排列的视图的固有Content_Size属性

请注意此处以外的单词。当.fill使用横向UIStackView不调整大小本身垂直使用布置子视图的尺寸。


3
这是没有黑客的正确解决方案。阅读文档总能带来回报!
Islam Q.

3
这应该是公认的解决方案。通过UIView解决方法,在我的情况下,UILabel的文本浮动在另一个子视图上。

14
它实际上不起作用...我的stackview中有3个标签。我将线设置为零,并对齐到中心...我仍然看到标签被切掉。
MatterGoal '18

11
这是.alignment该UIStackView的,你必须设置为任何东西,但.fill 不是在的UILabel,这是一个小中给出的例子混淆label.alignment = .center。我认为应该是stackView.alignment = .center
ae14

2
但是,如何在垂直StackView中使多行UILableView工作?
大春

42
  • 首先将标签行数设置为0
  • multiLine除非您将其设置为固定宽度,否则堆栈视图仍不会增长。当我们固定它的宽度时,当达到该宽度时,它会折断成多行,如下所示:

屏幕录像

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

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


3
如果堆栈视图的宽度不是固定的而是与设备(即超级视图)的宽度成比例的,该怎么办?
OutOnAWeekend,2013年

是的,我们也可以按比例设置宽度。关键是标签是否必须在某个宽度之后折断,无论是什么宽度但需要定义。
伊凡(Irfan),2016年

您可以preferredMaxLayoutWidth在@AnandKumar中指定viewDidLayoutSubviews标签,UIViewController也可以在layoutSubviews子类中指定@ UIView
Shyngys Kassymov'9

4
这应该是公认的答案,整个stackview的要点是不必在stackview及其元素之间添加约束...
Honey

4
赋予固定值会破坏自动布局的目的
Islam Q.

17

将preferredMaxLayoutWidth设置为UILabel对我有用

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

3
这是我书中的正确答案。每当您遇到UILabel的麻烦并且需要处理多行时,您确实需要为其提供一个PreferredMaxLayoutWidth。没有它可能会起作用,但是如果没有它,事情很快就会变得很时髦。
Mof

2
所有的人都尝试了所有答案,除了您的答案之外,所有答案都是错误的。谢谢!
莱万

这完美地解决了我的问题,并且让您感觉不那么客气了,谢谢。
Ethan Zhao

感谢您的回答!在我的情况下,我的stackView的对齐方式已设置为.center,我真的不需要UIView内的标签。
Fariza Zhumat

12

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

在此处输入图片说明


12
对于垂直stackView,需要将Distribution设置为“ Fill”才能起作用。
史努比协议

2
将分发设置为“填充”是修复的关键。
迪伦·摩尔

我发现对于垂直UIStackView,我必须为子UILabel设置顶部和底部约束,以展开和显示所有文本。
bruce1337

8

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

Swift 4示例:

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

5

该魔术对我来说是设置widthAnchorUIStackView

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


4

iOS 9+

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

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


4

这是一个UIStackViewUILabel具有自动高度的多线组成的垂直线的完整示例。

标签根据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])
    }
}

3

添加UIStackView属性,

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

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


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

1

系统布局应该弄清楚绘制子视图的原点,宽度和高度,在这种情况下,所有子视图都具有相同的优先级,这会产生冲突,布局系统不知道视图之间的依赖关系,哪个依赖关系首先绘制,然后依此类推

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


0

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


0

Xcode 9.2:

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

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

在此处输入图片说明


0

什么对我有用!

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

标签:中心,线= 0




0

对我来说,问题在于堆栈视图的高度太短了。标签和堆栈视图已正确设置为允许标签具有多行,但是标签是内容压缩的第一个牺牲品,而堆栈视图通常使用该标签来使其高度足够小。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.