I was able to reproduce this on iOS 13 and on iOS 14 (beta 3) - Filed another feedback (8115220) for this.
I dug a bit further into this and it seems that
UIButton isn't reporting the correct
intrinsicContentSize when bold text is enabled.
From a small experiment I subclassed
UIButton to print out the
intrinsicContentSize of the button itself and some of its subviews:
Code Block swiftprivate class Button: UIButton { |
|
override var intrinsicContentSize: CGSize { |
let size = super.intrinsicContentSize |
guard let imageView = imageView, let titleLabel = titleLabel else { |
return size |
} |
|
print(""" |
button.intrinsicContentSize = \(size) |
button.titleLabel.intrinsicContentSize = \(titleLabel.intrinsicContentSize) |
button.titleLabel.sizeThatFits = \(titleLabel.sizeThatFits(CGSize(width: .max, height: .max))) |
button.imageView.intrinsicContentSize = \(imageView.intrinsicContentSize) |
button.imageView.sizeThatFits = \(imageView.sizeThatFits(CGSize(width: .max, height: .max))) |
""") |
|
return size |
} |
|
} |
For a simple use case:
Code Block swift func makeButton() -> UIButton { |
let button = Button(type: .system) |
let image = UIImage(named: "menu") |
button.setImage(image, for: .normal) |
button.setTitle("Menu", for: .normal) |
return button |
} |
We get the following results
for Normal Text:
Code Block intrinsicContentSize = (68.0, 29.0) |
button.titleLabel..intrinsicContentSize = (38.5, 18.0) |
button.titleLabel..sizeThatFits = (38.5, 18.0) |
button.imageView.intrinsicContentSize = (29.0, 29.0) |
button.imageView.sizeThatFits = (29.0, 29.0) |
when Bold Text is enabled:
Code Block button.intrinsicContentSize = (69.0, 29.0) |
button.titleLabel.intrinsicContentSize = (40.0, 18.0) |
button.titleLabel.sizeThatFits = (40.0, 18.0) |
button.imageView.intrinsicContentSize = (29.0, 29.0) |
button.imageView.sizeThatFits = (30.0, 30.0) |
Notice the button's
imageView isn't reporting the correct
intrinsicContentSize when bold text is enabled, interestingly it does report the correct size when asking for
sizeThatFits!!
A workaround I found is to manually add the size diff to the intrinsic content size of the button,
but that isn't fool proof as there could be situations / configurations where that isn't correct.e.g.
Code Block swift override var intrinsicContentSize: CGSize { |
let size = super.intrinsicContentSize |
guard let imageView = imageView else { |
return size |
} |
|
let imageSizeThatFits = imageView.sizeThatFits(CGSize(width: .max, height: .max)) |
let imageIntrinsicSize = imageView.intrinsicContentSize |
|
let sizeDiff = CGSize(width: imageSizeThatFits.width - imageIntrinsicSize.width, |
height: imageSizeThatFits.height - imageIntrinsicSize.height) |
|
return CGSize(width: size.width + sizeDiff.width, |
height: size.height + sizeDiff.height) |
} |