I have an UILabel
(named label
) and an UITextField
(named textField
) set up such that they do have the same frame size and both do have adjustsFontSizeToFitWidth
enabled. In addition to that I set minimumFontSize
for textField
and a large initial font size for label
and textField
. This should - according to what I read - lead to "auto-shrink" the font size of the contained text. So far so good.
As a matter of fact this leads to shrinking of the text for both label
and textField
, but to my surprise with different results. While the label
font seams to be shrunk to fit the label bounding rectangle, the textField
font is shrunk to fit the textField
's width, but not its height. Here is a picture of the output (label
on top, textField
on bottom):
The documentation of UITextField.adjustsFontSizeToFitWidth
explicitly states:
Normally, the text field’s content is drawn with the font you specify in the font property. If this property is set to true, however, and the contents in the text property exceed the text field’s bounding rectangle, the receiver starts reducing the font size until the string fits or the minimum font size is reached. The text is shrunk along the baseline.
This leaves me confused about the shrinking behavior of textField
. Any ideas why this is happening? How do I achieve the same result for textField
as I do for label
?
Here is the complete playground code to generate the above image (I used autolayout, but the same thing happens when I use fixed frames):
import Foundation
import UIKit
import PlaygroundSupport
// setup liveView
var viewSize = CGSize(width: 400.0, height: 600.0)
let liveView = UIView(frame: CGRect(origin: CGPoint.zero, size: viewSize))
liveView.backgroundColor = UIColor.green
let topView = UIView()
topView.translatesAutoresizingMaskIntoConstraints = false
liveView.addSubview(topView)
topView.topAnchor.constraint(equalTo: liveView.topAnchor).isActive = true
topView.leftAnchor.constraint(equalTo: liveView.leftAnchor).isActive = true
topView.rightAnchor.constraint(equalTo: liveView.rightAnchor).isActive = true
topView.heightAnchor.constraint(equalTo: liveView.heightAnchor, multiplier: 0.5).isActive = true
let bottomView = UIView()
bottomView.translatesAutoresizingMaskIntoConstraints = false
liveView.addSubview(bottomView)
bottomView.bottomAnchor.constraint(equalTo: liveView.bottomAnchor).isActive = true
bottomView.leftAnchor.constraint(equalTo: liveView.leftAnchor).isActive = true
bottomView.rightAnchor.constraint(equalTo: liveView.rightAnchor).isActive = true
bottomView.heightAnchor.constraint(equalTo: liveView.heightAnchor, multiplier: 0.5).isActive = true
PlaygroundPage.current.liveView = liveView
// setup label
let labelSize = 0.5 * CGSize(width: liveView.frame.width, height: liveView.frame.height)
let label = UILabel(frame: CGRect(origin: CGPoint(x: 0.5 * labelSize.width, y: 0.5 * labelSize.height), size: labelSize))
label.numberOfLines = 1
label.text = "0"
label.adjustsFontSizeToFitWidth = true
label.font = UIFont(name: "Helvetica", size: 1000.0)
label.backgroundColor = UIColor.blue
label.translatesAutoresizingMaskIntoConstraints = false
topView.addSubview(label)
label.centerXAnchor.constraint(equalTo: topView.centerXAnchor).isActive = true
label.centerYAnchor.constraint(equalTo: topView.centerYAnchor).isActive = true
label.widthAnchor.constraint(equalTo: topView.widthAnchor, multiplier: 0.5).isActive = true
label.heightAnchor.constraint(equalTo: topView.heightAnchor, multiplier: 0.5).isActive = true
// setup textField
let textField = UITextField(frame: CGRect(origin: CGPoint(x: 0.5 * labelSize.width, y: 0.5 * labelSize.height), size: labelSize))
textField.text = "0"
textField.adjustsFontSizeToFitWidth = true
textField.minimumFontSize = 10.0
textField.font = UIFont(name: "Helvetica", size: 1000.0)
textField.backgroundColor = UIColor.blue
textField.translatesAutoresizingMaskIntoConstraints = false
bottomView.addSubview(textField)
textField.centerXAnchor.constraint(equalTo: bottomView.centerXAnchor).isActive = true
textField.centerYAnchor.constraint(equalTo: bottomView.centerYAnchor).isActive = true
textField.widthAnchor.constraint(equalTo: bottomView.widthAnchor, multiplier: 0.5).isActive = true
textField.heightAnchor.constraint(equalTo: bottomView.heightAnchor, multiplier: 0.5).isActive = true
I think it's fair to say that .adjustsFontSizeToFitWidth = true
only "mostly" works.
It is also primarily for use with string width.
Also, UILabel
and UITextField
do not use the same font rendering, and do not have the same bounding-box (text fields have an inset).
If you want both elements to have the same visual behaviors, your best bet is to use a UITextField
with user interaction disabled instead of a UILabel
.