Autoresize multiline UILabel in Swift
Asked Answered
H

5

1

I have tried everything to auto-resize my UILabel in Swift. I can autoresize the text when it is one line but when it is two lines it no longer works. The text in the UILabel changes often happening about every 10 seconds. The code I have tried is:

let direction = UILabel(frame: CGRect(x: 95, y: 10, width: screenWidth - 95, height:100))
direction.numberOfLines = 0
direction.adjustsFontSizeToFitWidth = true
direction.lineBreakMode = .byWordWrapping
direction.textAlignment = .center
direction.minimumScaleFactor = 0.2
direction.font = UIFont.boldSystemFont(ofSize: 40)
view.addSubview(direction)
direction.text = "Ffafdafafdfa fafda  dfafaf afa"

func updateDirection(update: String){
    direction.text = update
} 

The original text "Ffafdafafdfa fafda dfafaf afa" will automatically resize but when updateDirection is called the font size with not be changed from 40. I have also tried setting the number of lines to 2 and removing the .byWordWrapping. How can I get my UILabel to resize automatically?

Hinze answered 18/5, 2017 at 3:18 Comment(12)
What is the frame of your UILabel? Should your fontSize remain static or can change to sizeToFit?Thorp
@Imad I added the frame to the code. I need to change the font size but sizeToFit just changes the size of the frame and not the font.Hinze
@Imad Its already included. Look at the above codeHinze
Remove this line: direction.lineBreakMode = .byWordWrappingThorp
@Imad That does not have any affectHinze
It was working for me, if I don't have the constraints, with your code. The text came in multiple lines.Thorp
@Imad can you add an answer with your code?Hinze
Let us continue this discussion in chat.Thorp
let me know my answer works.Merchantable
@Merchantable alright thank u I'll let u know when I get homeHinze
code updated...Merchantable
@Merchantable it worked thank youHinze
M
2

Below code will keep the frame size and adjust the font size according with direction label content.

let backgroundView = UIView(frame: CGRect(x: 5, y: UINavigationController().navigationBar.frame.height + UIApplication.shared.statusBarFrame.height, width: UIScreen.main.bounds.width - 10, height: UIScreen.main.bounds.width - 100))
let direction = UILabel()

 override func viewDidLoad() {
    super.viewDidLoad()

 direction.backgroundColor = UIColor.green
 direction.numberOfLines = 0
 direction.textAlignment = .center
 direction.font = UIFont.boldSystemFont(ofSize: 40)
 direction.adjustsFontForContentSizeCategory = true
 direction.adjustsFontSizeToFitWidth = true
 direction.text = "This is some multiline label with a background colour" // Set or Initiate random function for your array here.

 backgroundView.backgroundColor = UIColor.red
 view.addSubview(backgroundView)
 backgroundView.addSubview(direction)

 Timer.scheduledTimer(timeInterval: 10.0, target: self, selector: #selector(random), userInfo: nil, repeats: true)  

 direction.translatesAutoresizingMaskIntoConstraints = false

 NSLayoutConstraint(item: direction,
                       attribute: .leading,
                       relatedBy: .equal,
                       toItem: backgroundView,
                       attribute: .leadingMargin,
                       multiplier: 1.0,
                       constant: 0.0).isActive = true

NSLayoutConstraint(item: direction,
                       attribute: .trailing,
                       relatedBy: .equal,
                       toItem: backgroundView,
                       attribute: .trailingMargin,
                       multiplier: 1.0,
                       constant: 0.0).isActive = true


NSLayoutConstraint(item: direction,
                       attribute: .top,
                       relatedBy: .equal,
                       toItem: backgroundView,
                       attribute: .topMargin,
                       multiplier: 1.0,
                       constant: 0.0).isActive = true

NSLayoutConstraint(item: direction,
                       attribute: .bottom,
                       relatedBy: .equal,
                       toItem: backgroundView,
                       attribute: .bottomMargin,
                       multiplier: 1.0,
                       constant: 0.0).isActive = true


}

func random(sender: Timer) {

    //Place your random func code here.     
}

Output:

enter image description here

Merchantable answered 18/5, 2017 at 13:52 Comment(5)
I need the text to fix inside a certain box though. This will resize the box to any heightHinze
Thank you for trying to help though. This has been very frustratingHinze
@SmedleyDSlap what you mean --This will resize the box to any height-- you mean font size?. If you resize the box depending on direction label content size then what's the point changing font size or scale or adjust font size?Merchantable
The gif linked in the answer has the box changing to different heights while the font size remains the same regardless of text length. I need the box to remain the same and the text size to changeHinze
thanks for this! especially the lines: direction.adjustsFontForContentSizeCategory = true direction.adjustsFontSizeToFitWidth = trueArber
T
0

Try this without Constraints:

    let direction = UILabel(frame: CGRect(x: 95, y: 10, width: 375 - 95, height:100))
    direction.numberOfLines = 0
    direction.adjustsFontSizeToFitWidth = true
    direction.textAlignment = .center
    direction.minimumScaleFactor = 0.2
    direction.font = UIFont.boldSystemFont(ofSize: 40)
    view.addSubview(direction)

    direction.text = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard"
Thorp answered 18/5, 2017 at 3:59 Comment(1)
The first time I set the text value it resizes but the second time it does not resizeHinze
A
0

I will try this code It is use full

first create one function

func calchight(strin:String) -> CGFloat
   {
       let label =  UILabel(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: CGFloat.greatestFiniteMagnitude))
       label.numberOfLines = 0
        label.text = strin
       label.sizeToFit()
        return label.frame.height + 2
   }

then call this function in your right place, when you want to resize label

/--------------

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
    { 
        let heit = self.calchight(strin: StringObject)

        return (heit)
    }

/--------------------------

this code is useful and not require Auto layout containers

Anathema answered 18/5, 2017 at 4:28 Comment(0)
P
0

UILabel will consider its content size to be one line of text, even when numberOfLines is set to a non-zero value, unless preferredMaxLayoutWidth is also set.

In other words, it can't predict how to wrap the text without preferredMaxLayoutWidth, so it doesn't plan to. It seems like during the autolayout process, a UILabel doesn't know how to balance the priority between its width set by layout constraints outside of it and the wrapping of text.

So it doesn't exert any additional pressure (more than the height of one line) on the vertical dimension even when its Content Compression Resistance is higher than other views', because it will assume that by exerting pressure in the horizontal axis, its content will be displayed.

So the solution is to set preferredMaxLayoutWidth, so that it is able to determine the height of the content after wrapping the text and then it uses that content size to negotiate layout with other views.

You probably want to avoid hard-coding the width of your UILabel. Assuming that its container's width is not going to change based on autolayout, it should be safe to use that. In this case I'm in a UITableViewCell or UICollectionViewCell and the "title label" spans the full width of the cell.

override func layoutSubviews() {
    // Tell the label it should wrap text at the same width as this cell's contentView.
    titleLabel.preferredMaxLayoutWidth = contentView.frame.width

    super.layoutSubviews()
}
Pekingese answered 26/4, 2021 at 14:41 Comment(0)
I
-1

Try using function sizetofit() after assigning text to your label. like:

direction.sizeToFit()
Ironmonger answered 18/5, 2017 at 4:34 Comment(4)
This changes the frame of the UILabel and does not change the font sizeHinze
try removing line direction.lineBreakMode = .byWordWrappingIronmonger
I tried but it not work I updated the question with more detailsHinze
try below code: let direction = UILabel(frame: CGRect(x: 95, y: 10, width: UIScreen.main.bounds.width - 100, height:100)); direction.numberOfLines = 0 direction.adjustsFontSizeToFitWidth = true direction.textAlignment = .center direction.font = UIFont.boldSystemFont(ofSize: 40) self.view.addSubview(direction) direction.text = "abc " direction.backgroundColor = UIColor.lightGrayIronmonger

© 2022 - 2024 — McMap. All rights reserved.