How do I set adaptive multiline UILabel text?

IosSwift

Ios Problem Overview


I have a UILabel named titleLabel in my storyboard nib set to its default height. I want it to programatically expand in height to fit it's content. Here is what I have tried so far:

// 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()

None of this works for me in any combination! I always only see one line of text in my UILabel. What am I doing wrong?

I absolutely need the text content to be variable.

Ios Solutions


Solution 1 - Ios

I kind of got things working by adding auto layout constraints:

auto layout contraints

But I am not happy with this. Took a lot of trial and error and couldn't understand why this worked.

Also I had to add to use titleLabel.numberOfLines = 0 in my ViewController

Solution 2 - Ios

I know it's a bit old but since I recently looked into it :

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

First set the numberOfLines property to 0 so that the device understands you don't care how many lines it needs. Then specify your favorite BreakMode Then the width needs to be set before sizeToFit() method. Then the label knows it must fit in the specified width

Solution 3 - Ios

This is much better approach if you are looking for multiline dynamic text label which exactly takes the space based on its text.

No sizeToFit, preferredMaxLayoutWidth used

Below is how it will work.

enter image description here

Lets set up the project. Take a Single View application and in Storyboard Add a UILabel and a UIButton. Define constraints to UILabel as below snapshot:

enter image description here

Set the Label properties as below image:

enter image description here

Add the constraints to the UIButton. Make sure that vertical spacing of 100 is between UILabel and UIButton

enter image description here

Now set the priority of the trailing constraint of UILabel as 749

enter image description here

Now set the Horizontal Content Hugging and Horizontal Content Compression properties of UILabel as 750 and 748

enter image description here

Below is my controller class. You have to connect UILabel property and Button action from storyboard to viewcontroller class.

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.
}


}

Thats it. This will automatically resize the UILabel based on its content and also you can see the UIButton is also adjusted accordingly.

Solution 4 - Ios

It should work. Try this

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);

Solution 5 - Ios

With Graphical User Interface (GUI) in Xcode, you can do the following:

> - Go to "Attribute Inspector" and set Lines value to 0. By default, it is set to 1. > - The Label text can be written in multi-line by hitting option + return.

enter image description here

> - Now, go to "Size Inspector" and set the width, height, X & Y position of the Label.

enter image description here

That's all.

Solution 6 - Ios

Programmatically, Swift

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

Solution 7 - Ios

Programmatically in Swift 5 with Xcode 10.2

Building on top of @La masse's solution, but using autolayout to support rotation

Set anchors for the view's position (left, top, centerY, centerX, etc). You can also set the width anchor or set the frame.width dynamically with the UIScreen extension provided (to support rotation)

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()

If setting frame.width dynamically using UIScreen:

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

Solution 8 - Ios

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() in the end will shrink the label's width to the widest line after word break

Solution 9 - Ios

This has worked for me:

  • Set the numberOfLines property of UILabel to 0
  • add this line: yourLabel.sizeToFit() after assigning text to the UILabel

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAmit ErandoleView Question on Stackoverflow
Solution 1 - IosAmit ErandoleView Answer on Stackoverflow
Solution 2 - IosLa masseView Answer on Stackoverflow
Solution 3 - IosArun GuptaView Answer on Stackoverflow
Solution 4 - IosBhumeshwer katreView Answer on Stackoverflow
Solution 5 - IosMukesh ChapagainView Answer on Stackoverflow
Solution 6 - Iosuser1023102View Answer on Stackoverflow
Solution 7 - Ioseharo2View Answer on Stackoverflow
Solution 8 - IosSiamasterView Answer on Stackoverflow
Solution 9 - IostausunView Answer on Stackoverflow