将动态类型添加到 UISearchBar

Posted

技术标签:

【中文标题】将动态类型添加到 UISearchBar【英文标题】:Add dynamic type to a UISearchBar 【发布时间】:2018-07-31 01:57:49 【问题描述】:

我的问题在标题中几乎已经说明。我正在尝试将动态类型(定义为here)添加到UISearchBar,但没有成功。我知道这是可能的,因为系统应用程序似乎能够很好地处理它,如下所示:

但是,我的应用似乎并没有很好地处理这些问题,如下所示:

知道UITextField 包含在UISearchBar 中,我自然尝试了这个解决方案,但没有成功: UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).adjustsFontForContentSizeCategory = true

我也尝试过在线搜索/检查文档,但我似乎无法在任何地方找到解决方案。我是否缺少在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 
            $0.subviews.forEach 
                if let textField = $0 as? UITextField 
                    _textField = textField
                
            
        
        return _textField
    

【问题讨论】:

“动态类型”是什么意思?目前尚不清楚您的问题是什么。并且标签dynamictype 似乎与您的问题没有任何关系(阅读标签说明)。 糟糕,我的错。我的意思是“动态类型:在此处定义:developer.apple.com/design/human-interface-guidelines/ios/…。我会更新问题。 @matt 嗯.. 我以前看过那个视频,现在又在看。我相信它只会让你得到一个基于文本样式的理想间距/理想字体。您认为您可以将我链接到特定的 API,我可以看看吗? 【参考方案1】:

我遵循这些里程碑来实现您的目标:

使用动态类型功能自动调整字体(步骤 1)

当新的preferred content size category 出现时,调整搜索栏约束(STEP 2) AND 其文本字段约束(STEP 3)。 p>

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])


我使用您帖子中提供的代码 sn-p 来获取搜索栏文本字段:

extension UISearchBar 

    var textField: UITextField? 

        var _textField: UITextField? = nil

        subviews.forEach 
            $0.subviews.forEach 
                if let textField = $0 as? UITextField 
                    _textField = textField
                
            
        
        return _textField
    

但是,您也可以使用密钥searchField 获取它,如下所示:

let textField = searchBar.value(forKey: "searchField") as? UITextField

下面的快照显示了最终结果:

您现在可以将动态类型添加到 UISearchBar,方法是调整上面的代码 sn-p 并自定义视觉个人选择(文本样式、字体、边距...).

【讨论】:

这非常有效。你能告诉我们为什么文本字段的高度和宽度需要常数 -20 吗? 我不记得了,对不起:我建议更改值并注意外观的变化。

以上是关于将动态类型添加到 UISearchBar的主要内容,如果未能解决你的问题,请参考以下文章

动态添加的控件最终包装在通用类型中? [关闭]

动态创建匿名类型? [复制]

Elasticsearch动态模板设置

如何动态添加新的图表类型到谷歌烛台图表

C# 动态添加类动态添加类型代码添加类型

如何从QML基本类型列表中动态删除元素?