为 UISearchBar 添加动态类型

6
我的问题基本上已经在标题中说明了。我尝试为UISearchBar添加动态类型(如此处定义),但没有成功。我知道这是可能的,因为系统应用程序似乎可以处理它,如此处所示: enter image description here 然而,我的应用程序似乎没有很好地处理它,如下所示:

enter image description here

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

我还尝试在网上搜索/查看文档,但似乎找不到解决方案。我是否缺少某些内容以使动态类型在UISearchBar中起作用?

更新: @matt建议我进行手动检查并以此方式更新字体。但是,这会产生另一个问题,因为搜索栏本身太小而无法容纳文本,如下所示: enter image description here

@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”似乎与你的问题无关(请阅读标签描述)。 - rmaddy
糟糕,我的错。我是指在此处定义的“动态类型”:https://developer.apple.com/design/human-interface-guidelines/ios/visual-design/typography/。我会更新问题。 - Harish
@matt 嗯..我以前看过那个视频,现在又再次观看。我认为它只能让你根据文本样式获得理想的间距/理想的字体。你觉得你能给我提供具体的API链接,我可以看一下吗? - Harish
1个回答

2
我遵循以下里程碑来实现你的目标:

我最初的回答:

  • Automatically Adjusts Font with the Dynamic Type feature (STEP 1).
  • Adapt the searchbar constraints (STEP 2) AND its textfield constraints (STEP 3) when a new preferred content size category occurs.

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

我使用了您在帖子中提供的代码片段来获取搜索栏文本字段:

最初的回答:

我用你发帖中提供的代码片段获得了搜索栏的文本字段:

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

以下是最终结果的快照: enter image description here 现在,您可以通过调整上面的代码片段并自定义视觉个人选择(文本样式、字体、边距等)来为UISearchBar添加动态类型。

这个完美地运作。你能告诉我为什么我们需要在文本框高度和宽度上减去常数-20吗? - Reshma
我不记得了,抱歉:我建议更改值并注意外观上的变化。 - XLE_22

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接