I have 3 UILabels
and I want to set same (the smallest one from all of 3 possibilities) font for all of them. What is the problem? I don\'t know how to check the cu
use this extention
extension String {
func height(withConstrainedWidth width: CGFloat, font: UIFont) -> CGFloat {
let constraintRect = CGSize(width: width, height: .greatestFiniteMagnitude)
let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)
return ceil(boundingBox.height)
}
}
get height
height = strDesc.height(withConstrainedWidth: UIScreen.main.bounds.size.width - 160, font: UIFont.systemFont(ofSize: 14.0))
What I've found is that inside viewDidLoad()
your constraints are not fully defined yet. You can try to do these calculations in another method for example viewWillAppear()
or any other that suits you and is executed after viewDidLoad()
.
This is one way to get the current size of the UILabel pointsize although I know of more ways if this does not work. This is the cleanest and fastest. See example and extension included.
import UIKit
class ViewController: UIViewController {
lazy var label1 : UILabel = {
let lbl = UILabel(frame: CGRect(x: 20, y: 80, width: self.view.bounds.width - 40, height: 40))
lbl.text = "This is some large text to make it fit to size with a big font size"
lbl.font = UIFont.systemFont(ofSize: 50, weight: .bold)
lbl.textColor = .black
lbl.minimumScaleFactor = 0.01
lbl.adjustsFontSizeToFitWidth = true
lbl.numberOfLines = 0
return lbl
}()
lazy var label2 : UILabel = {
let lbl = UILabel(frame: CGRect(x: 20, y: label1.frame.maxY + 5, width: self.view.bounds.width - 40, height: 40))
lbl.text = "This is one line"
lbl.font = UIFont.systemFont(ofSize: 20, weight: .bold)
lbl.textColor = .black
lbl.minimumScaleFactor = 0.01
lbl.adjustsFontSizeToFitWidth = true
lbl.numberOfLines = 0
return lbl
}()
lazy var label3 : UILabel = {
let lbl = UILabel(frame: CGRect(x: 20, y: label2.frame.maxY + 10, width: self.view.bounds.width - 40, height: 80))
lbl.text = "This is some large text to make it fit to size with a big font size"
lbl.font = UIFont.systemFont(ofSize: 100, weight: .bold)
lbl.textColor = .black
lbl.minimumScaleFactor = 0.01
lbl.adjustsFontSizeToFitWidth = true
lbl.numberOfLines = 0
return lbl
}()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.view.addSubview(label1)
self.view.addSubview(label2)
self.view.addSubview(label3)
var minSize : CGFloat = .greatestFiniteMagnitude
for sub in self.view.subviews{
if let lbl = sub as? UILabel{
//get the size
let font = lbl.adjustedFont()
print("the size is \(font.pointSize)")
minSize = min(font.pointSize,minSize)
}
}
print("the minimum for all fonts is \(minSize)")
print("i am going to delay for 3 seconds and then reset all the labels to the minimum size :)")
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 3.0) {
for sub in self.view.subviews{
if let lbl = sub as? UILabel{
lbl.font = lbl.font.withSize(minSize)
}
}
}
}
}
extension UILabel{
func adjustedFont()->UIFont {
guard let txt = text else {
return self.font
}
let attributes: [NSAttributedString.Key: Any] = [.font: self.font]
let attributedString = NSAttributedString(string: txt, attributes: attributes)
let drawingContext = NSStringDrawingContext()
drawingContext.minimumScaleFactor = self.minimumScaleFactor
attributedString.boundingRect(with: bounds.size,
options: [.usesLineFragmentOrigin,.usesFontLeading],
context: drawingContext)
let fontSize = font.pointSize * drawingContext.actualScaleFactor
return font.withSize(CGFloat(floor(Double(fontSize))))
}
}
Example in Action