Swift中如何通过代码实现无障碍字体大小动态调整?
实现APP内滑块全局调整字体大小(兼容系统无障碍规则)
核心思路
基于系统原生动态字体机制,通过自定义缩放因子/点数偏移叠加系统字体样式,同时用通知实现全局字体刷新,既保留系统「更大字体」的无障碍适配,又支持APP内滑块自主调整。
步骤1:全局存储调整参数
用UserDefaults持久化APP内的字体调整值,重启APP后依然生效:
extension UserDefaults { // 若用比例缩放(推荐,符合无障碍缩放逻辑),默认值1.0(无额外缩放) var customFontScale: CGFloat { get { CGFloat(double(forKey: "CustomFontScale")) } set { set(Double(newValue), forKey: "CustomFontScale") } } // 若用固定点数偏移(如滑块使字号+2),默认值0(无偏移) var customFontPointOffset: CGFloat { get { CGFloat(double(forKey: "CustomFontPointOffset")) } set { set(Double(newValue), forKey: "CustomFontPointOffset") } } } // 初始化默认值(首次启动时调用) UserDefaults.standard.register(defaults: [ "CustomFontScale": 1.0, "CustomFontPointOffset": 0.0 ])
步骤2:封装字体获取方法
封装全局工具方法,在系统偏好字体基础上叠加自定义调整,同时保留系统动态字体特性:
extension UIFont { // 方案1:比例缩放(推荐,和系统动态字体逻辑一致) static func preferredScaledFont(forTextStyle style: UIFont.TextStyle) -> UIFont { let baseFont = UIFont.preferredFont(forTextStyle: style) let metrics = UIFontMetrics(forTextStyle: style) // 叠加APP内自定义缩放比例 return metrics.scaledFont(for: baseFont, multiplier: UserDefaults.standard.customFontScale) } // 方案2:固定点数偏移(如滑块使字号增加2) static func preferredOffsetFont(forTextStyle style: UIFont.TextStyle) -> UIFont { let baseFont = UIFont.preferredFont(forTextStyle: style) let adjustedSize = baseFont.pointSize + UserDefaults.standard.customFontPointOffset let metrics = UIFontMetrics(forTextStyle: style) // 确保系统动态调整依然生效 return metrics.scaledFont(for: UIFont(descriptor: baseFont.fontDescriptor, size: adjustedSize)) } }
步骤3:滑块控制与全局通知
滑块调整时更新存储的参数,并发送通知触发所有控件刷新字体:
// 定义全局通知名 extension Notification.Name { static let customFontChanged = Notification.Name("CustomFontChanged") } // 滑块事件处理(示例用比例缩放,点数偏移逻辑类似) @IBAction func fontSliderValueChanged(_ sender: UISlider) { // 滑块范围建议设为0.8~1.4(缩小20%到放大40%) UserDefaults.standard.customFontScale = CGFloat(sender.value) // 通知全局刷新字体 NotificationCenter.default.post(name: .customFontChanged, object: nil) }
步骤4:控件适配字体刷新
让需要适配的控件监听通知,自动更新字体:
// 自定义Label(直接复用已有UILabel也可,在ViewController中监听通知) class AutoAdjustLabel: UILabel { override init(frame: CGRect) { super.init(frame: frame) setupFont() } required init?(coder: NSCoder) { super.init(coder: coder) setupFont() } private func setupFont() { // 保留系统动态字体适配 adjustsFontForContentSizeCategory = true // 初始设置字体 updateFont() // 监听字体调整通知 NotificationCenter.default.addObserver( self, selector: #selector(updateFont), name: .customFontChanged, object: nil ) } @objc private func updateFont() { // 根据需求选择比例缩放或点数偏移方案 font = .preferredScaledFont(forTextStyle: .body) // font = .preferredOffsetFont(forTextStyle: .body) } deinit { NotificationCenter.default.removeObserver(self) } }
额外适配:系统控件(导航栏、TabBar等)
对导航栏、TabBar等系统控件,可在AppDelegate或SceneDelegate中监听通知,统一更新字体:
func setupSystemFontObserver() { NotificationCenter.default.addObserver(forName: .customFontChanged, object: nil, queue: .main) { _ in // 更新导航栏标题字体 UINavigationBar.appearance().titleTextAttributes = [ .font: UIFont.preferredScaledFont(forTextStyle: .headline) ] // 更新TabBar字体 UITabBar.appearance().itemTextAttributes = [ .font: UIFont.preferredScaledFont(forTextStyle: .caption1) ] } }
内容的提问来源于stack exchange,提问作者manubrio
相关产品推荐
相关产品推荐

