You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 16:31:02