How to create dynamic label size programmatically in swift?

15,962

Solution 1

You can access label intrinsic property after you have given the text to label then you can give the frame.

Swift 3:

let label = UILabel()
label.text = "Your text here"
label.textAlignment = .center
label.font = UIFont.systemFont(ofSize: 14)
label.frame = CGRect(x:0,y:0,width:label.intrinsicContentSize.width,height:label.intrinsicContentSize.height)

you can check some conditions based on the intrinsicContentSize.

Hope it helps.

Solution 2

This label has a defined width but not a defined height. The height is determined by the amount of text in the label. If you removed the width, the label would not break into lines, which is not what you want. The sizeToFit() method called at the end sets the height of the label after it knows how many lines of text it needs to break into based on the label's text. If this isn't what you wanted, let me know.

let label = UILabel()
label.text = "scones"
label.numberOfLines = 0 // 0 = as many lines as the label needs
label.frame.origin.x = 32
label.frame.origin.y = 32
label.frame.size.width = view.bounds.width - 64
label.font = UIFont.displayHeavy(size: 17) // my UIFont extension
label.textColor = UIColor.black
label.sizeToFit()
view.addSubview(label)

Solution 3

You can use the following to calculate the string height and width and then set them:

import Foundation
import UIKit

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        let width = "Hello World".stringWidth // 74.6
        let height = "Hello World".stringHeight // 16.7

        let headerLabel = UILabel()
        headerLabel.frame = CGRect(x: 0, y: 0, width: width, height: height)
        headerLabel.center = CGPoint(x: screenSize.width/2, y: 245)
    }
}

extension String {
    var stringWidth: CGFloat {
        let constraintRect = CGSize(width: UIScreen.main.bounds.width, height: .greatestFiniteMagnitude)
        let boundingBox = self.trimmingCharacters(in: .whitespacesAndNewlines).boundingRect(with: constraintRect, options: [.usesLineFragmentOrigin, .usesFontLeading], attributes: [NSAttributedStringKey.font: UIFont.systemFont(ofSize: 14)], context: nil)
        return boundingBox.width
    }

    var stringHeight: CGFloat {
        let constraintRect = CGSize(width: UIScreen.main.bounds.width, height: .greatestFiniteMagnitude)
        let boundingBox = self.trimmingCharacters(in: .whitespacesAndNewlines).boundingRect(with: constraintRect, options: [.usesLineFragmentOrigin, .usesFontLeading], attributes: [NSAttributedStringKey.font: UIFont.systemFont(ofSize: 14)], context: nil)
        return boundingBox.height
    }
}
Share:
15,962
SwiftyJD
Author by

SwiftyJD

Updated on June 04, 2022

Comments

  • SwiftyJD
    SwiftyJD about 2 years

    I'm trying to create a label programmatically in Swift but the issue I'm having is that based on the data model the amount of text can change thereby changing the size of the label. Typically I would create the label like this before knowing the text:

    headerLabel.frame = CGRect(x: 0, y: 0, width: screenSize.width/2.5, height: screenSize.height/45)
    headerLabel.center = CGPoint(x: screenSize.width/2, y: 245)
    

    But in this case the text can be any amount ranging from a line to a paragraph so hard coding the height won't work. How to create the label so it would accommodate any amount of text?

  • Scooter
    Scooter about 5 years
    You used label.intrinsicContentSize.width for both width and height.
  • Rafaela Lourenço
    Rafaela Lourenço over 4 years
    Thanks!! It helped.. +10 :)