如何设置自适应多行 UILabel 文本?

Posted

技术标签:

【中文标题】如何设置自适应多行 UILabel 文本?【英文标题】:How do I set adaptive multiline UILabel text? 【发布时间】:2014-06-10 07:08:22 【问题描述】:

我的 storyboard 笔尖中有一个名为 titleLabelUILabel 设置为默认高度。我希望它以编程方式扩展高度以适应它的内容。到目前为止,这是我尝试过的:

// just setting content
titleLabel.text = "You don't always know what you are getting with mass-market cloud computing services. But with SimpliCompute, the picture is clear. SimpliCompute gives you powerful virtual servers you can deploy using just your web browser. That’s enterprise grade technology you can deploy and control on-the-fly."

titleLabel.numberOfLines = 0

titleLabel.preferredMaxLayoutWidth = 700

titleLabel.lineBreakMode = NSLineBreakMode.ByWordWrapping

titleLabel.sizeToFit()

任何组合都不适合我!我总是在我的UILabel 中看到一行文字。我做错了什么?

我绝对需要文本内容是可变的。

【问题讨论】:

您是否尝试将高度设置为非常高的值? 数以千计? 你在使用自动布局吗?因为那时你应该调用更新约束方法。 如果开启则表示您正在使用它,您只需在界面生成器中添加正确的约束即可。或者关闭自动布局。 与任何 IBOutlet 或 IBAction 一样,您只需将一条线从情节提要中的约束拖到您的控制器。此连接将是 NSLayoutConstraint 类型,然后您可以设置 constraint.constant = 500 来设置新高度。 【参考方案1】:

我通过添加自动布局约束让事情变得正常:

但我对此并不满意。进行了大量的试验和错误,无法理解为什么会这样。

我还必须在我的ViewController 中添加使用titleLabel.numberOfLines = 0

【讨论】:

@MarcMosby 你能解释一下为什么会这样吗?此外,我没有在我的控制器等中添加任何插座。 为什么您对自己的解决方案不满意? numberofLines = 0 表示 numberOfLines 是无穷大。至于你的约束,你有一个固定的宽度和一个动态的高度。如果你想根据文本的数量动态设置标签的高度,我可以给你一个代码 sn-p 来告诉你如何做到这一点。 我想我很不高兴,因为我不太了解自动布局。但我现在正在补救。感谢您的快速解释并为我指明了正确的方向。能否也给我那个代码 sn-p 以供参考? 哇,这个想法让我很开心!!我想 2 年后你已经知道为什么了,但是它起作用了,因为有了顶部约束,你给出了它必须开始的点,如果它需要额外的线条,它会增长到底部,因为标签或底部约束没有固定的高度.【参考方案2】:

我知道它有点旧,但因为我最近查看了它:

let l = UILabel()
l.numberOfLines = 0
l.lineBreakMode = .ByWordWrapping
l.text = "BLAH BLAH BLAH BLAH BLAH"
l.frame.size.width = 300
l.sizeToFit()

首先将 numberOfLines 属性设置为 0,以便设备了解您并不关心它需要多少行。 然后指定你最喜欢的 BreakMode 然后需要在 sizeToFit() 方法之前设置宽度。然后标签知道它必须适合指定的宽度

【讨论】:

这不是一个好的解决方案。想想所有不同的屏幕尺寸,包括纵向和横向。将宽度静态设置为 300 对它们来说并不是很好。 @Sti 你是对的。但您可以按如下方式动态设置宽度:l.frame.size.width = UIScreen.main.bounds.width * percentage。然后,标签的宽度将根据屏幕的宽度进行调整。显然,这是一个虚拟示例,您可以根据设备是 iPad 还是 iPhone 等进行调整。 这仍然不是动态的。旋转设备时它不起作用。 你的方向是对的。根据我对这个解决方案的回忆,我想我一直在使用viewWillTransitionNotificationCenter 类。虽然,我会为任何最近的项目使用故事板的约束,即使它不能很好地与本机 UIScrollView 是的,但是在 TableViewCells 中使用viewWillTransition?嗯。【参考方案3】:

如果您正在寻找多行动态文本标签,该标签恰好根据其文本占用空间,这是更好的方法。

没有 sizeToFit,使用了preferredMaxLayoutWidth

下面是它的工作原理。

让我们设置项目。使用 Single View 应用程序并在 Storyboard 中添加 UILabel 和 UIButton。定义 UILabel 的约束如下快照:

如下图设置标签属性:

将约束添加到 UIButton。确保 UILabel 和 UIButton 之间的垂直间距为 100

现在将 UILabel 的尾随约束的优先级设置为 749

现在将 UILabel 的 Horizo​​ntal Content Hugging 和 Horizo​​ntal Content Compression 属性设置为 750 和 748

下面是我的控制器类。您必须将故事板中的 UILabel 属性和 Button 操作连接到 viewcontroller 类。

import UIKit

class ViewController: UIViewController 

@IBOutlet weak var textLabel: UILabel!
var count = 0
let items = ["jackson is not any more in this world", "Jonny jonny yes papa eating sugar no papa", "Ab", "What you do is what will happen to you despite of all measures taken to reverse the phenonmenon of the nature"]


@IBAction func updateLabelText(sender: UIButton) 
    if count > 3 
        count = 0
    
    textLabel.text = items[count]
    count = count + 1


override func viewDidLoad() 
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    //self.textLabel.sizeToFit()
    //self.textLabel.preferredMaxLayoutWidth = 500


override func didReceiveMemoryWarning() 
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.




就是这样。这将根据 UILabel 的内容自动调整其大小,您还可以看到 UIButton 也相应地调整了。

【讨论】:

精湛的解决方案兄弟..!!脱帽 效果很好.. 你能解释一下为什么你把优先级改为 749 吗? 阿伦,我有一个类似的问题试图完成相同的结果,但到目前为止我收到的所有建议都不起作用。你能在这里看看我的帖子:***.com/questions/46716123/… 并帮助我解决我的约束问题吗?你在这里的帖子很棒!【参考方案4】:

它应该工作。试试这个

var label:UILabel = UILabel(frame: CGRectMake(10
    ,100, 300, 40));
label.textAlignment = NSTextAlignment.Center;
label.numberOfLines = 0;
label.font = UIFont.systemFontOfSize(16.0);
label.text = "First label\nsecond line";
self.view.addSubview(label);

【讨论】:

但我不想设置明确的框架,因为文本内容会是可变的 您可以获得字符串的大小,并将该 size.height 应用于标签 一定有更好的方法不是吗?这听起来像是一个糟糕的解决方案。 ios8 布局旨在适应和灵活 是的,我同意。但需要探索。如果您发现任何问题,请回答它,这样也会对其他人有所帮助。 您应该可以只使用 .Center。 swift中有类型推断,由于属性是NSTextAlignment类型,所以不需要放在那里。【参考方案5】:

使用 Xcode 中的图形用户界面 (GUI),您可以执行以下操作:

转到“Attribute Inspector”并将Lines 值设置为0。默认设置为1。 点击option + return,标签文本可以多行书写。

现在,转到“Size Inspector”并设置标签的widthheightXYposition

就是这样。

【讨论】:

问题如何设置文本左上角对齐?【参考方案6】:

以编程方式,Swift

label.lineBreakMode = NSLineBreakMode.byWordWrapping
label.titleView.numberOfLines = 2

【讨论】:

【参考方案7】:

在带有 Xcode 10.2 的 Swift 5 中以编程方式

建立在@La masse 的解决方案之上,但使用自动布局来支持旋转

为视图的位置设置锚点(left、top、centerY、centerX 等)。您还可以设置宽度锚点或使用提供的 UIScreen 扩展动态设置 frame.width(以支持旋转)

label = UILabel()
label.numberOfLines = 0
label.lineBreakMode = .byWordWrapping
self.view.addSubview(label)
// SET AUTOLAYOUT ANCHORS
label.translatesAutoresizingMaskIntoConstraints = false
label.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: 20).isActive = true
label.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: -20).isActive = true
label.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 20).isActive = true
// OPTIONALLY, YOU CAN USE THIS INSTEAD OF THE WIDTH ANCHOR (OR LEFT/RIGHT)
// label.frame.size = CGSize(width: UIScreen.absoluteWidth() - 40.0, height: 0)
label.text = "YOUR LONG TEXT GOES HERE"
label.sizeToFit()

如果使用 UIScreen 动态设置 frame.width:

extension UIScreen    // OPTIONAL IF USING A DYNAMIC FRAME WIDTH
    class func absoluteWidth() -> CGFloat 
        var width: CGFloat
        if UIScreen.main.bounds.width > UIScreen.main.bounds.height 
            width = self.main.bounds.height // Landscape
         else 
            width = self.main.bounds.width // Portrait
        
        return width
    

【讨论】:

self.leftAnchor 来自哪里? .leftAnchor 是来自 superView 的 NSLayoutAnchor... 示例代码认为 UILabel 嵌入在另一个视图(自身)中。为了更容易理解,我把它改成了self.view(假设UILabel是在ViewController的视图中添加的) 您的答案不应使用外部混淆变量。示例代码应反映最小的 workable 属性。【参考方案8】:
extension UILabel 

    var textSize: CGSize  text?.size(withAttributes: [.font: font!]) ?? .zero 

    func setSizeForText(_ str: String, maxWidth: CGFloat) 
        text = str
        let dividedByMaxWidth = Int(textSize.width / maxWidth)
        if dividedByMaxWidth == 0 
            frame.size = textSize
         else 
            numberOfLines = dividedByMaxWidth + 1
            frame.size = CGSize(width: maxWidth, height: frame.size.height * CGFloat(numberOfLines))
            sizeToFit()
        
    

sizeToFit() 最后将标签的宽度缩小到分词后最宽的行

【讨论】:

【参考方案9】:

这对我有用:

UILabelnumberOfLines属性设置为0 在将文本分配给UILabel 之后添加这一行:yourLabel.sizeToFit()

【讨论】:

以上是关于如何设置自适应多行 UILabel 文本?的主要内容,如果未能解决你的问题,请参考以下文章

ios之UILabel实现文本自适应方法

swift UILabel多行显示时 计算UILable的高度(可用于UILable高度自适应)

iOS 根据给定宽度自适应文字大小

UILabel 多行文本缩放字体以适应 \n

iOS 设置UILabel的行间距并自适应高度

C# winform Label控件 已经自适应实现多行显示了 我现在要取出每行的文本 该怎么做? 求助! 多谢!