如何在 iOS 故事板中使用自定义字体来支持动态类型辅助功能大小

How to honor Dynamic Type Accessibility Sizes with a custom font in an iOS storyboard

如何使用 dynamic type text style "Title 1" 并将字体设置为故事板中 UILabel 的内置字体 Chalkboard SE?

我需要遵守 iOS 中的动态字体大小(Apple 自 iOS 7 以来一直鼓励这样做?)我还需要使用内置字体 Chalkboard SE,它不是默认用于 "text styles" 字体。我目前使用的是自定义字体,如图所示,但需要根据用户的动态类型/辅助功能大小更改字体大小就像所有 Text Styles 字体一样。最好的 Text Styles 选项是 Title 1,但 font/typeface 是不可接受的。

虽然您不能通过 Storyboard 同时指定自定义字体和首选文本样式,但以编程方式为您的自定义字体指定动态类型大小并不困难:

Swift:

let pointSize  = UIFontDescriptor.preferredFontDescriptorWithTextStyle(UIFont‌​TextStyleTitle1).poi‌​ntSize
let customFont = UIFont(name: "Chalkboard SE", size: pointSize)

当您收到 UIContentSizeCategoryDidChangeNotification 时,使用相同的代码更新标签的字体。

对象 C:

 CGFloat pointSize = [[UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleHeadline] pointSize];
 [titleLabel setFont:[UIFont fontWithName:@"Marker Felt" size:pointSize]];

无需监听 NSNotification.Name.UIContentSizeCategoryDidChange.

即可尝试我的解决方案

只需覆盖任何 UIView 或 UITableViewCell 上的 traitCollectionDidChange 和 update/calulate 具有类似 TextStyle 的字体大小。

您可以在 MacOS 上使用任何模拟设备和 Accessibility Inspector 对其进行简单测试。

 override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
       super.traitCollectionDidChange(previousTraitCollection)

        let pointSize = UIFontDescriptor.preferredFontDescriptor(withTextStyle: .title1).pointSize
        titleLabel.font = titleLabel.font.withSize(pointSize)
    }

我们必须添加相关 UIFramework 的所有扩展,我们必须在 iOS-11+ 中使用自定义字体的动态字体大小,例如 UILabel、UIButton、UITextField、UITextView。 swift 4.2 中给出了代码。我们只需要使用这些自定义 类 而不是原生 ios 类 来查看动态字体在应用程序中的效果。

首先是标签:

class AppLabel: UILabel {

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
    super.traitCollectionDidChange(previousTraitCollection)
    if #available(iOS 11.0, *)  {

        self.font = UIFontMetrics.default.scaledFont(for: self.font)
        self.adjustsFontForContentSizeCategory = true
        // Fallback on earlier versions
    } else {
        // Fallback on earlier versions
    }
  }

}

第二个是 UIButton:

class AppButton: UIButton {

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
    super.traitCollectionDidChange(previousTraitCollection)
    if #available(iOS 11.0, *) {

        self.titleLabel?.font = UIFontMetrics.default.scaledFont(for: self.titleLabel?.font ?? UIFont())
        self.titleLabel?.adjustsFontForContentSizeCategory = true
    } else {
        // Fallback on earlier versions 
    }
  }
}

第三个是 UITextField:

class AppTextField: UITextField {
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
    super.traitCollectionDidChange(previousTraitCollection)
    if #available(iOS 11.0, *) {

        self.font = UIFontMetrics.default.scaledFont(for: self.font ?? UIFont())
        self.adjustsFontForContentSizeCategory = true
    } else {
        // Fallback on earlier versions
    }
  }
}

UITextView 中的最后一个:

class AppTextView: UITextView {

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
    super.traitCollectionDidChange(previousTraitCollection)
    if #available(iOS 11.0, *) {

        self.font = UIFontMetrics.default.scaledFont(for: self.font ?? UIFont())
        self.adjustsFontForContentSizeCategory = true
    } else {
        // Fallback on earlier versions
    }
  }
}