如何在iOS应用中全局修改preferredFont并保留字体动态缩放?
自定义字体适配iOS动态字体缩放的解决方案
针对你需要用自定义字体同时保留动态缩放能力的需求,提供以下两种可行方案:
方案一:全局统一替换系统偏好字体
通过扩展UIFont封装自定义的偏好字体方法,方便全局调用,确保整个APP内的文本样式统一且支持动态缩放:
extension UIFont { /// 获取适配指定文本样式的自定义动态字体 static func preferredFuturaFont(forTextStyle style: UIFont.TextStyle) -> UIFont { // 获取对应文本样式的系统偏好字体大小 let baseSize = UIFont.preferredFont(forTextStyle: style).pointSize // 加载自定义字体,加载失败则回退到系统字体 guard let customFont = UIFont(name: "Futura-Medium", size: baseSize) else { return UIFont.preferredFont(forTextStyle: style) } // 利用UIFontMetrics实现基于系统字体大小的动态缩放 let metrics = UIFontMetrics(forTextStyle: style) return metrics.scaledFont(for: customFont) } }
使用时直接替换原有的preferredFont调用即可:
var attributes = [NSAttributedString.Key: Any]() attributes[.font] = UIFont.preferredFuturaFont(forTextStyle: .body) attributes[.foregroundColor] = UIColor.black
方案二:局部控件使用自定义动态字体
如果仅需在特定控件中使用自定义动态字体,可直接通过UIFontMetrics对自定义字体进行缩放处理:
var attributes = [NSAttributedString.Key: Any]() let textStyle = UIFont.TextStyle.body // 1. 获取对应文本样式的系统基准字号 let baseSize = UIFont.preferredFont(forTextStyle: textStyle).pointSize // 2. 加载自定义字体 guard let baseCustomFont = UIFont(name: "Futura-Medium", size: baseSize) else { // 加载失败时回退到系统偏好字体 attributes[.font] = UIFont.preferredFont(forTextStyle: textStyle) attributes[.foregroundColor] = UIColor.black return } // 3. 生成支持动态缩放的字体 let scaledFont = UIFontMetrics(forTextStyle: textStyle).scaledFont(for: baseCustomFont) attributes[.font] = scaledFont attributes[.foregroundColor] = UIColor.black
额外注意:监听字体大小变化
无论使用哪种方案,都需要监听系统字体大小变更通知,确保控件字体实时更新:
// 在视图控制器的viewDidLoad中添加监听 override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.addObserver( self, selector: #selector(updateLabelFont), name: UIContentSizeCategory.didChangeNotification, object: nil ) } // 实现更新字体的方法 @objc private func updateLabelFont() { // 重新设置label的attributedText或font let attributes = // 重新生成包含动态字体的属性字典 yourLabel.attributedText = NSAttributedString(string: yourText, attributes: attributes) } // 记得在deinit中移除监听 deinit { NotificationCenter.default.removeObserver(self) }
内容的提问来源于stack exchange,提问作者Wasko Ltd
相关产品推荐
相关产品推荐

