UILabel wrong word wrap in iOS 11
This is a change by Apple to prevent widowed lines. From a design perspective, it is preferred to avoid having a single word on a line of text. UILabel now breaks the line in a way that the second line of text always has at least 2 words on it.
See the answer below for an option to disable it.
Also here's a good article about "widowed" and "orphaned" text.
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()
}
}
This should work in most circumstances. I tested with your text and more text. You can see both in the example above.
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 word wrap feature leaving space even when sufficient space available for the word
You may want to give this a try...
Subclass UITextView
, disable scrolling, editing and selecting... set the textContainerInset = UIEdgeInsets.zero
and textContainer.lineFragmentPadding = 0
to Zero.
Result:
Code (@IBDesignable
so we can see it in IB / Storyboard):
@IBDesignable
class TextViewLabel: UITextView {
override init(frame: CGRect, textContainer: NSTextContainer?) {
super.init(frame: frame, textContainer: textContainer)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
func commonInit() -> Void {
isScrollEnabled = false
isEditable = false
isSelectable = false
textContainerInset = UIEdgeInsets.zero
textContainer.lineFragmentPadding = 0
}
}
How to wrap text UILabel Xcode with Storyboard settings
You need to add leading
and trailing
constraint to your label
Or you can add a width constraint relative to the superview width
Related Topics
Uilocalnotification Is Deprecated in iOS 10
Xcode 7 Swift 2 Impossible to Instantiate Uiviewcontroller Subclass of Generic Uitableviewcontroller
Realmswift: Convert Results to Swift Array
How to Disable Caching in Alamofire
How to Remove HTML Tags from Nsstring in Iphone
How to Programmatically Fake a Touch Event to a Uibutton
Where to Remove Observer for Nsnotification in Swift
Swift 3 Core Data Delete Object
Wkwebview Open Links from Certain Domain in Safari
How to Use Avfoundation to Crop a Video
Firebase Cloud Messaging - Check Existing or Available Topics
Swift - Which Types to Use? Nsstring or String
Uiscreen Mainscreen Bounds Returning Wrong Size
iOS How to Detect When App Was Removed from Process
Rotation Methods Deprecated, Equivalent of 'Didrotatefrominterfaceorientation'
Xcode 10 (iOS 12) Does Not Contain Libstdc++6.0.9
How to Add Equal Spacing and Equal Width for Button in iOS Auto Layout