向 UISearchBar 添加动态类型
Add dynamic type to a UISearchBar
我的问题在标题中已经说得很清楚了。我正在尝试将动态类型(定义为 here)添加到 UISearchBar
,但没有成功。我知道这是可能的,因为系统应用程序似乎能够很好地处理它,如下所示:
但是,我的应用似乎没有像此处所示那样很好地处理该问题:
知道 UITextField
包含在 UISearchBar
中,我自然尝试了这个解决方案但没有成功:
UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).adjustsFontForContentSizeCategory = true
我也尝试搜索 online/checking 文档,但我似乎无法在任何地方找到解决方案。在 UISearchBar
.
中使用动态类型是否缺少某些东西
更新:
@matt 建议我手动检查并以这种方式更新字体。然而,这会产生另一个问题,因为搜索栏本身太小而无法容纳如下所示的文本:
@matt 建议也使用 scaledValue(for:)
方法更新高度,但这似乎不起作用。这是我正在使用的代码:
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))
}
字体现在似乎随着这个更新的代码而缩放,但搜索栏的高度没有增加:
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))
}
}
此外,这是我找到 textField 的方式(以防其他遇到问题的用户想知道):
extension UISearchBar {
var textField: UITextField? {
var _textField: UITextField? = nil
subviews.forEach {
[=12=].subviews.forEach {
if let textField = [=12=] as? UITextField {
_textField = textField
}
}
}
return _textField
}
}
我已遵循这些里程碑来实现您的目标:
- 使用动态类型功能自动调整字体(第 1 步)。
调整搜索栏约束(第 2 步)AND 其文本字段约束(第 3 步) 当出现新的 preferred content size category 时。
class SearchBarDynamicTypeVC: UIViewController {
@IBOutlet weak var mySearchBar: UISearchBar!
let fontHead = UIFont(name: "Chalkduster", size: 20.0)
let fontHeadMetrics = UIFontMetrics(forTextStyle: .title1)
var initialFrameHeight: CGFloat = 0.0
override func viewDidLoad() {
super.viewDidLoad()
UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).font = fontHeadMetrics.scaledFont(for: fontHead!)
mySearchBar.textField?.adjustsFontForContentSizeCategory = true //STEP 1
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
initialFrameHeight = mySearchBar.intrinsicContentSize.height
if let textField = mySearchBar.textField {
adaptConstraints(textField) //Initialization according to the first preferred content size category
}
}
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
if let textField = mySearchBar.textField,
let _ = previousTraitCollection {
adaptConstraints(textField) // STEP 2 & 3
}
}
private func adaptConstraints(_ textField: UITextField) {
// Adapt the SEARCHBAR constraints
mySearchBar.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.deactivate(mySearchBar.constraints)
let heightSB = mySearchBar.heightAnchor.constraint(equalToConstant: fontHeadMetrics.scaledValue(for: initialFrameHeight))
let widthSB = mySearchBar.widthAnchor.constraint(equalToConstant: UIScreen.main.bounds.width - 20)
let centerVSB = mySearchBar.centerYAnchor.constraint(equalTo: self.view.centerYAnchor)
let centerHSB = mySearchBar.centerXAnchor.constraint(equalTo: self.view.centerXAnchor)
NSLayoutConstraint.activate([centerVSB,
centerHSB,
widthSB,
heightSB])
// Adapt the SEARCHBAR TEXTFIELD constraints
textField.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.deactivate(textField.constraints)
let centerXTF = textField.centerXAnchor.constraint(equalTo: textField.superview!.centerXAnchor)
let centerYTF = textField.centerYAnchor.constraint(equalTo: textField.superview!.centerYAnchor)
let widthTF = textField.widthAnchor.constraint(equalTo: textField.superview!.widthAnchor, constant: -20.0)
let heightTF = textField.heightAnchor.constraint(equalTo: textField.superview!.heightAnchor, constant: -20.0)
NSLayoutConstraint.activate([centerXTF,
centerYTF,
widthTF,
heightTF])
}
}
我使用了您 post 中提供的代码片段来获取搜索栏文本字段:
extension UISearchBar {
var textField: UITextField? {
var _textField: UITextField? = nil
subviews.forEach {
[=11=].subviews.forEach {
if let textField = [=11=] as? UITextField {
_textField = textField
}
}
}
return _textField
}
}
不过,您也可以使用密钥 searchField
获取它,如下所示:
let textField = searchBar.value(forKey: "searchField") as? UITextField
以下截图为最终结果:
您现在可以通过调整上面的代码片段并自定义视觉个人选择向 UISearchBar 添加动态类型 (文本样式、字体、边距.. .).
我的问题在标题中已经说得很清楚了。我正在尝试将动态类型(定义为 here)添加到 UISearchBar
,但没有成功。我知道这是可能的,因为系统应用程序似乎能够很好地处理它,如下所示:
但是,我的应用似乎没有像此处所示那样很好地处理该问题:
知道 UITextField
包含在 UISearchBar
中,我自然尝试了这个解决方案但没有成功:
UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).adjustsFontForContentSizeCategory = true
我也尝试搜索 online/checking 文档,但我似乎无法在任何地方找到解决方案。在 UISearchBar
.
更新:
@matt 建议我手动检查并以这种方式更新字体。然而,这会产生另一个问题,因为搜索栏本身太小而无法容纳如下所示的文本:
@matt 建议也使用 scaledValue(for:)
方法更新高度,但这似乎不起作用。这是我正在使用的代码:
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))
}
字体现在似乎随着这个更新的代码而缩放,但搜索栏的高度没有增加:
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))
}
}
此外,这是我找到 textField 的方式(以防其他遇到问题的用户想知道):
extension UISearchBar {
var textField: UITextField? {
var _textField: UITextField? = nil
subviews.forEach {
[=12=].subviews.forEach {
if let textField = [=12=] as? UITextField {
_textField = textField
}
}
}
return _textField
}
}
我已遵循这些里程碑来实现您的目标:
- 使用动态类型功能自动调整字体(第 1 步)。
调整搜索栏约束(第 2 步)AND 其文本字段约束(第 3 步) 当出现新的 preferred content size category 时。
class SearchBarDynamicTypeVC: UIViewController { @IBOutlet weak var mySearchBar: UISearchBar! let fontHead = UIFont(name: "Chalkduster", size: 20.0) let fontHeadMetrics = UIFontMetrics(forTextStyle: .title1) var initialFrameHeight: CGFloat = 0.0 override func viewDidLoad() { super.viewDidLoad() UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).font = fontHeadMetrics.scaledFont(for: fontHead!) mySearchBar.textField?.adjustsFontForContentSizeCategory = true //STEP 1 } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) initialFrameHeight = mySearchBar.intrinsicContentSize.height if let textField = mySearchBar.textField { adaptConstraints(textField) //Initialization according to the first preferred content size category } } override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { super.traitCollectionDidChange(previousTraitCollection) if let textField = mySearchBar.textField, let _ = previousTraitCollection { adaptConstraints(textField) // STEP 2 & 3 } } private func adaptConstraints(_ textField: UITextField) { // Adapt the SEARCHBAR constraints mySearchBar.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.deactivate(mySearchBar.constraints) let heightSB = mySearchBar.heightAnchor.constraint(equalToConstant: fontHeadMetrics.scaledValue(for: initialFrameHeight)) let widthSB = mySearchBar.widthAnchor.constraint(equalToConstant: UIScreen.main.bounds.width - 20) let centerVSB = mySearchBar.centerYAnchor.constraint(equalTo: self.view.centerYAnchor) let centerHSB = mySearchBar.centerXAnchor.constraint(equalTo: self.view.centerXAnchor) NSLayoutConstraint.activate([centerVSB, centerHSB, widthSB, heightSB]) // Adapt the SEARCHBAR TEXTFIELD constraints textField.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.deactivate(textField.constraints) let centerXTF = textField.centerXAnchor.constraint(equalTo: textField.superview!.centerXAnchor) let centerYTF = textField.centerYAnchor.constraint(equalTo: textField.superview!.centerYAnchor) let widthTF = textField.widthAnchor.constraint(equalTo: textField.superview!.widthAnchor, constant: -20.0) let heightTF = textField.heightAnchor.constraint(equalTo: textField.superview!.heightAnchor, constant: -20.0) NSLayoutConstraint.activate([centerXTF, centerYTF, widthTF, heightTF]) } }
我使用了您 post 中提供的代码片段来获取搜索栏文本字段:
extension UISearchBar {
var textField: UITextField? {
var _textField: UITextField? = nil
subviews.forEach {
[=11=].subviews.forEach {
if let textField = [=11=] as? UITextField {
_textField = textField
}
}
}
return _textField
}
}
不过,您也可以使用密钥 searchField
获取它,如下所示:
let textField = searchBar.value(forKey: "searchField") as? UITextField
以下截图为最终结果:
您现在可以通过调整上面的代码片段并自定义视觉个人选择向 UISearchBar 添加动态类型 (文本样式、字体、边距.. .).