在SwiftUI应用中实现全局生效的文本大小选择器
在SwiftUI中实现全局文本大小控制
1. 构建全局字体缩放管理类
通过ObservableObject维护用户选择的缩放系数,让整个应用能响应字体大小变化:
import SwiftUI class FontScaleManager: ObservableObject { // 默认与系统标准字体比例一致,可自定义初始值 @Published var scaleFactor: CGFloat = UIFont.preferredFont(forTextStyle: .body).pointSize / 17.0 // 根据文本样式返回缩放后的字体 func scaledFont(for style: UIFont.TextStyle, weight: UIFont.Weight = .regular) -> Font { let baseFont = UIFont.preferredFont(forTextStyle: style) let scaledSize = baseFont.pointSize * scaleFactor return .system(size: scaledSize, weight: weight) } }
2. 将管理器注入应用环境
在App入口把FontScaleManager加入环境,确保所有子视图都能访问:
@main struct YourApp: App { @StateObject private var fontScaleManager = FontScaleManager() var body: some Scene { WindowGroup { ContentView() .environmentObject(fontScaleManager) } } }
3. 实现文本大小选择器
创建用户可交互的选择控件,比如分段选择器或滑块:
struct FontSizePickerView: View { @EnvironmentObject var fontScaleManager: FontScaleManager // 自定义缩放档位,可按需调整 let scaleOptions: [CGFloat] = [0.8, 0.9, 1.0, 1.1, 1.2, 1.3] var body: some View { Picker("文本大小", selection: $fontScaleManager.scaleFactor) { ForEach(scaleOptions, id: \.self) { scale in Text(scale == 1.0 ? "标准" : scale > 1.0 ? "大\(Int((scale-1)*100))%" : "小\(Int((1-scale)*100))%") .tag(scale) } } .pickerStyle(.segmented) .padding() } }
4. 适配自定义视图文本
在自定义视图中,直接调用管理器的scaledFont方法设置字体:
struct ContentView: View { @EnvironmentObject var fontScaleManager: FontScaleManager var body: some View { NavigationStack { List { Text("示例文本") .font(fontScaleManager.scaledFont(for: .body)) FontSizePickerView() } .navigationTitle("全局字体设置") // 自定义导航栏标题字体 .toolbar { ToolbarItem(placement: .principal) { Text("全局字体设置") .font(fontScaleManager.scaledFont(for: .title1)) } } } } }
5. 适配TabBar、NavigationBar等系统组件
系统原生组件需要通过UIKit桥接修改字体,结合通知监听缩放系数变化:
@main struct YourApp: App { @StateObject private var fontScaleManager = FontScaleManager() init() { // 初始化系统组件字体 updateTabBarFont() updateNavigationBarFont() // 监听缩放变化通知,更新系统组件字体 NotificationCenter.default.addObserver(forName: NSNotification.Name("FontScaleChanged"), object: nil, queue: .main) { _ in updateTabBarFont() updateNavigationBarFont() } } private func updateTabBarFont() { let scaledSize = 10 * fontScaleManager.scaleFactor let tabBarFont = UIFont.systemFont(ofSize: scaledSize, weight: .medium) UITabBarItem.appearance().setTitleTextAttributes([.font: tabBarFont], for: .normal) UITabBarItem.appearance().setTitleTextAttributes([.font: tabBarFont], for: .selected) } private func updateNavigationBarFont() { let scaledSize = 17 * fontScaleManager.scaleFactor let navBarFont = UIFont.systemFont(ofSize: scaledSize, weight: .semibold) UINavigationBar.appearance().titleTextAttributes = [.font: navBarFont] } var body: some Scene { WindowGroup { TabView { ContentView() .tabItem { Image(systemName: "house") Text("首页") } // 添加其他Tab项 } .environmentObject(fontScaleManager) .onChange(of: fontScaleManager.scaleFactor) { _ in // 发送通知触发系统组件字体更新 NotificationCenter.default.post(name: NSNotification.Name("FontScaleChanged"), object: nil) } } } }
6. 可选:联动系统辅助功能字体
如果需要和系统动态字体大小联动,在FontScaleManager中添加监听:
extension FontScaleManager { func setupSystemFontObserver() { NotificationCenter.default.addObserver(forName: UIContentSizeCategory.didChangeNotification, object: nil, queue: .main) { _ in let baseSize = UIFont.preferredFont(forTextStyle: .body).pointSize scaleFactor = baseSize / 17.0 // 保持用户设置的相对缩放比例 } } }
在App初始化时调用fontScaleManager.setupSystemFontObserver()即可。
内容的提问来源于stack exchange,提问作者ayelvs
相关产品推荐
相关产品推荐

