My question is pretty much stated in the title. I'm trying to add dynamic type (as defined here) to a UISearchBar
with no luck. I know this is possible as the system apps seem to be able to handle it just fine as shown here:
However, my app doesn't seem to be handling that so well as shown here:
Knowing that UITextField
is contained within UISearchBar
I naturally tried this solution without success:
UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).adjustsFontForContentSizeCategory = true
I've also tried searching online/checking documentation but I can't seem to find a solution anywhere. Is there something I'm missing to get dynamic type working in a UISearchBar
.
Update:
@matt suggested I do a manual check and update the font that way. However, that is yielding another issue as the search bar itself is too small to fit the text as shown here:
@matt suggested to update the height as well using the scaledValue(for:)
method, however this doesn't seem to work. Here's the code I'm using:
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).font = UIFont.preferredFont(forTextStyle: .body)
let textFieldFrame = UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).frame
UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).frame = CGRect(x: textFieldFrame.minX, y: textFieldFrame.minY, width: textFieldFrame.width, height: UIFontMetrics.default.scaledValue(for: textFieldFrame.height))
}
The font seems to now be scaling with this updated code, yet the search bar's height isn't growing:
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
searchBar.textField?.font = UIFont.preferredFont(forTextStyle: .body)
if let textFieldFrame = searchBar.textField?.frame {
searchBar.textField?.frame = CGRect(x: textFieldFrame.minX, y: textFieldFrame.minY, width: textFieldFrame.width, height: UIFontMetrics.default.scaledValue(for: textFieldFrame.height))
}
}
Also, here's how I found the textField (just in case other users who get stuck would like to know):
extension UISearchBar {
var textField: UITextField? {
var _textField: UITextField? = nil
subviews.forEach {
$0.subviews.forEach {
if let textField = $0 as? UITextField {
_textField = textField
}
}
}
return _textField
}
}
I have followed these milestones to reach your goal:
Adapt the searchbar constraints (STEP 2) AND its textfield constraints (STEP 3) when a new preferred content size category occurs.
I used the code snippet provided in your post to get the searchbar textfield:
However, you can also get it using the key
searchField
as follows:The snapshots hereunder show the final result:
You can now add dynamic type to a UISearchBar by adapting the code snippet above and customizing the visual personal choices (text style, font, margins...).