Uilabel Text Not Wrapping

UILabel Text Not Wrapping

First, the good news: You have set the label to 2 lines and Word Wrap. So it can wrap. Excellent.

Now you must make sure the label is tall enough. Either give it no height constraint, or give it a big enough height constraint that it can accommodate two lines.

Finally, you must limit its width. This is what causes the text to wrap. If you don't limit the label's width, it will just keep growing rightward, potentially continuing off the screen. The limit on the label's width stops this rightward growth and causes the text to wrap (and the label to grow downward instead).

You can limit width in several ways. You can have an actual width constraints. Or you can have a leading constraint and a trailing constraint, to something relatively immovable, such as the superview. And there is a third way: on the Size inspector (which you do also show, at the bottom right of your question), set the Preferred Width (it is shown at the top of the Size inspector): this is the width at which, all other things being equal, the label will stop growing to the right and wrap and grow down instead.

UILabel can not be wrapped and aligned at the same time

You are missing a few constraints.

To get a multiline label to wrap, it must have its width limited (how else would it know the text is too long?).

To get auto layout to adjust the cell's height, you need constraints on the content of the cell to "push down" the bottom of the cell.

So...

  • Constrain your top-left label to Leading: 0, Top: 0, Width: 77 (I'm using 77 as the width, based on your images).
  • Constrain your top-right label to Leading: 8 (to top-left label's trailing), Top: 0, Trailing: 0
  • Constrain your bottom-left label to Leading: 0, Top: 8 (to top-left label's bottom), Width: 77 (or, width equal to top-left label)
  • Constrain your bottom-right label to Leading: 8 (to bottom-left label's trailing), Top: 8 (to top-right label's bottom, or Top: 0 to top of bottom-left label), Trailing: 0

then, add Bottom constraints of >= 0 to each of the bottom labels.

I'm guessing either bottom label may wrap to multiple lines, so set each one to Number of Lines: 0

The layout:

Sample Image

the result:

Sample Image

How to wrap text UILabel Xcode with Storyboard settings

You need to add leading and trailing constraint to your label

Sample Image

Or you can add a width constraint relative to the superview width

Sample Image

Multiline text label not wrapping in Swift

You need to constrain its width, either through it's anchors or explicitly giving it a width.

Word wrap not working in UILabel

Try this. It should shrink the font just enough to fit the longest word on a line. If you see a better way let me know as I would love to improve this.I am sure I could adapt it to work in IB.

import UIKit

extension UILabel{

func adjustedFont()->UIFont {
let attributes: [NSAttributedStringKey: Any] = [.font: font]
let attributedString = NSAttributedString(string: text ?? "", attributes: attributes)
let drawingContext = NSStringDrawingContext()
drawingContext.minimumScaleFactor = minimumScaleFactor

attributedString.boundingRect(with: bounds.integral.size,
options: .usesLineFragmentOrigin,
context: drawingContext)

let fontSize = font.pointSize * drawingContext.actualScaleFactor

return font.withSize(fontSize)
}

func fitMaxWord(){
layoutIfNeeded()
let scaledFont = self.adjustedFont()
let currentFont = scaledFont
if let txt = text,
let maxString = txt.components(separatedBy: " ").max(by: {$1.count > $0.count})?.replacingOccurrences(of: "\n", with: ""){
let maxFontSize: CGFloat = currentFont.pointSize
let minFontSize: CGFloat = 5.0


var q = maxFontSize
var p = minFontSize
let height = currentFont.lineHeight
let constraintSize = CGSize(width: .greatestFiniteMagnitude, height: height)
var sizedFont = currentFont
while(p <= q){
let currentSize = (p + q) / CGFloat(2)
sizedFont = currentFont.withSize( CGFloat(currentSize) )

let text = NSMutableAttributedString(string:maxString, attributes:[NSAttributedStringKey.font:sizedFont])

let textRect = text.boundingRect(with: constraintSize, options: [.usesLineFragmentOrigin], context: nil).integral
let labelSize = textRect.width

//1 is a fudge factor
if labelSize == ceil(self.bounds.width - 1){
break
}else if labelSize > ceil(self.bounds.width - 1){
q = currentSize - 0.1
}else{
p = currentSize + 0.1
}
}

if sizedFont.pointSize < currentFont.pointSize{
self.font = sizedFont
}
}
}
}

Minimum example:

import UIKit

class ViewController: UIViewController {

override func viewDidLoad() {
super.viewDidLoad()

//we could test longer text
//
let text = "CHULALONGKORN UNIVERSITY Plus a lot of additional text to make sure it still does not clip a word"
let testLabel = UILabel(frame: .zero)
//testLabel.text = "CHULALONGKORN UNIVERSITY"
testLabel.text = text
testLabel.numberOfLines = 0
testLabel.textAlignment = .center
testLabel.font = UIFont.systemFont(ofSize: 45)
testLabel.adjustsFontSizeToFitWidth = true //unneeded in this instance but lets set it
testLabel.minimumScaleFactor = 0.3
self.view.addSubview(testLabel)
testLabel.translatesAutoresizingMaskIntoConstraints = false
testLabel.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 20).isActive = true
testLabel.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -20).isActive = true
testLabel.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 50).isActive = true
self.view.layoutIfNeeded()
testLabel.fitMaxWord()
}


}

ExampleImage
This should work in most circumstances. I tested with your text and more text. You can see both in the example above.

UILabel text doesn't word wrap

Just found the problem, my numberOfLines was still at 1. After setting it to 0 it works fine.

UILabel not wrapping reliably

The key to getting it to work correctly was to ask the view to reset the layout after the constraints had been applied and all the text had been set. I merely added these lines to my custom UITableViewCell after I had set the data that it needed:

    //set data
//set constraints

...

contentView.setNeedsLayout()
contentView.layoutIfNeeded()
}

I realized this was the solution because the view kept reporting their initial frame sizes instead of sizes after being affected by their constraints. For some reason, all the other views looked correct but not the UILabels.

I found the solution in the answer posted here: https://stackoverflow.com/a/13542580/1637033

UILabel not wrapping after the text is changed

When you change the text in a label in a table view cell, the table view does not automatically re-calculate cell sizes.

To do so, you either reload the data - as you've seen - or, execute these two lines:

tableView.beginUpdates()
tableView.endUpdates()

If you are updating the text in the label from inside your cell class, you'' want to use a delegate / protocol pattern to tell the table view controller to execute those two lines.



Related Topics



Leave a reply



Submit