UIButton 的属性标题的动态类型

Cra*_*rds 4 accessibility uibutton uikit ios dynamic-type-feature

有谁有动态类型的工作attributedTitleUIButton?考虑下面的超级简单代码:

let font = UIFont(name: "Helvetica", size: 14)!
let scaledFont = UIFontMetrics.default.scaledFont(for: font)

let button = UIButton(type: .custom)
button.titleLabel?.font = scaledFont
button.titleLabel?.adjustsFontForContentSizeCategory = true

let attributes: [NSAttributedString.Key: Any] = [ .font: scaledFont ]
let attributedText = NSAttributedString(string: "Press me", attributes: attributes)
button.setAttributedTitle(attributedText, for: .normal)
Run Code Online (Sandbox Code Playgroud)

如果我使用辅助功能检查器上下缩放字体大小,按钮的大小和标签文本不能正确缩放。

但是,如果我只是调用button.setTitle()传递一个普通字符串,动态类型缩放工作正常。

直接在 a 上对属性文本使用相同的模式UILabel效果很好......似乎只是当我将属性文本用于 aUIButton的标题时。

任何想法或建议都会很棒。谢谢

编辑:再戳一下后,看起来正在发生的事情是文本正在尝试缩放,但按钮的宽度/高度并没有随之增长。如果我将动态类型拨号到最大文本大小,然后创建屏幕并继续缩小字体大小,则它可以正常工作,因为按钮的宽度/高度约束设置为初始大值。但是如果我从一个小的动态类型设置开始并变大,按钮就不能适应文本大小的变化

XLE*_*_22 9

如果我使用辅助功能检查器上下缩放字体大小,按钮的大小和标签文本不能正确缩放。

要缩放的的归属字符串标签UIButtonDynamic Type首先设置标题标签作为归因串,然后把这个元件在setAttributedTitle按钮方法。

关于按钮大小,在协议sizeToFittraitCollectionDidChange实例方法中指定按钮的方法(使用约束也可以是另一种解决方案)UITraitEnvironment

我在 Xcode 中创建了一个空白项目,如下所示: 在此处输入图片说明

复制粘贴下面的代码片段(Swift 5.0,iOS 12)

class ViewController: UIViewController {

    @IBOutlet weak var myButton: UIButton!

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
    
        myButton.layer.borderColor = UIColor.black.cgColor
        myButton.layer.borderWidth = 4.0
    
        myButton.contentEdgeInsets = UIEdgeInsets(top: 10,
                                                  left: 20,
                                                  bottom: 10,
                                                  right: 20)
        
        let font = UIFont(name: "Helvetica", size: 19)!
        let scaledFont = UIFontMetrics.default.scaledFont(for: font)

        let attributes = [NSAttributedString.Key.font: scaledFont]
        let attributedText = NSAttributedString(string: "Press me",
                                                attributes: attributes)
        
        myButton.titleLabel?.attributedText = attributedText
        myButton.setAttributedTitle(myButton.titleLabel?.attributedText,
                                    for: .normal)

        myButton.titleLabel?.adjustsFontForContentSizeCategory = true
    }


    override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
    
        myButton.sizeToFit()
    }
}
Run Code Online (Sandbox Code Playgroud)

......你会得到以下结果: 在此处输入图片说明 如果您需要进一步解释,我建议您查看包含{代码片段 + 插图} 的这种动态类型教程,以及有关使用动态类型构建应用程序的WWDC 详细摘要

?? 编辑 2021/02/15 ??

感谢@Anthony 的评论,我将这个旧的解决方案改进为新的上下文,如下所示:

override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        myButton.layer.borderColor = UIColor.black.cgColor
        myButton.layer.borderWidth = 4.0

        let font = UIFont(name: "Helvetica", size: 20)!
        let scaledFont = UIFontMetrics.default.scaledFont(for: font)

        let attributes = [NSAttributedString.Key.font: scaledFont]
        let attributedText = NSAttributedString(string: "Press Me Huge Button",
                                                attributes: attributes)

        myButton.titleLabel?.attributedText = attributedText
        myButton.titleLabel?.numberOfLines = 0
        myButton.titleLabel?.textAlignment = .center
        
        myButton.setAttributedTitle(attributedText,
                                    for: .normal)

        myButton.titleLabel?.adjustsFontForContentSizeCategory = true
        
        createConstraints()
    }
Run Code Online (Sandbox Code Playgroud)

...并在按钮及其内容之间添加约束:

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
    
    DispatchQueue.main.async() {
        self.myButton.setNeedsUpdateConstraints() // For updating constraints.
    }
}

private func createConstraints() {
    
    myButton.translatesAutoresizingMaskIntoConstraints = false
    myButton.titleLabel?.translatesAutoresizingMaskIntoConstraints = false
    
    let spacing = 10.0
    myButton.titleLabel?.trailingAnchor.constraint(equalTo: myButton.trailingAnchor,
                                                   constant: -CGFloat(spacing)).isActive = true
    myButton.titleLabel?.leadingAnchor.constraint(equalTo: myButton.leadingAnchor,
                                                  constant: CGFloat(spacing)).isActive = true
    myButton.titleLabel?.topAnchor.constraint(equalTo: myButton.topAnchor,
                                              constant: CGFloat(spacing)).isActive = true
    myButton.titleLabel?.bottomAnchor.constraint(equalTo: myButton.bottomAnchor,
                                                 constant: -CGFloat(spacing)).isActive = true
}
Run Code Online (Sandbox Code Playgroud)

通过对内部按钮的一些新约束Interface Builder,我终于使用Xcode 环境覆盖窗格获得了这些屏幕截图: 在此处输入图片说明 在此处输入图片说明