SwiftUI中限制Dynamic Type适配容器尺寸的实现方案咨询
限制SwiftUI自定义字体的Dynamic Type缩放范围
要解决动态文本缩放超出容器的问题,核心是通过UIFontMetrics控制自定义字体的最大缩放级别,替代原生.custom(_:size:relativeTo:)的无限制缩放逻辑。
实现步骤
1. 添加自定义字体缩放工具方法
借助UIKit的UIFontMetrics创建带缩放限制的字体,再转换为SwiftUI可用的Font类型:
import UIKit // 扩展你的CustomFont类型,添加缩放限制方法 extension CustomFont { // 按动态文本样式限制最大缩放(示例限制到.title1级别,可根据需求调整) func scaledFont(withMaxTextStyle maxStyle: UIFont.TextStyle = .title1) -> Font { guard let baseUIFont = UIFont(name: name, size: size) else { // 自定义字体加载失败时,回退到系统对应样式字体 return .system(size: size, relativeTo: dynamicTypeReference.uiTextStyle) } // 基于基准动态样式创建字体度量器 let metrics = UIFontMetrics(forTextStyle: dynamicTypeReference.uiTextStyle) // 限制最大缩放对应的文本样式 let scaledUIFont = metrics.scaledFont(for: baseUIFont, maximumTextStyle: maxStyle) return Font(scaledUIFont) } // 可选:直接指定最大字号限制 func scaledFont(withMaxPointSize maxSize: CGFloat) -> Font { guard let baseUIFont = UIFont(name: name, size: size) else { return .system(size: size, relativeTo: dynamicTypeReference.uiTextStyle) } let metrics = UIFontMetrics(forTextStyle: dynamicTypeReference.uiTextStyle) let scaledUIFont = metrics.scaledFont(for: baseUIFont, maximumPointSize: maxSize) return Font(scaledUIFont) } } // 让你的DynamicTypeReference枚举对应到UIKit的文本样式 extension DynamicTypeReference { // 替换为你项目中实际的枚举类型名 var uiTextStyle: UIFont.TextStyle { switch self { case .body: return .body case .headline: return .headline case .subheadline: return .subheadline // 补充你项目中所有对应的样式映射 default: return .body } } }
2. 修改Text样式实现
替换原来的.font修饰符调用,使用带缩放限制的字体:
struct CustomTextStyle: TextStyling { var styleCategory: StyleCategory var dynamicScalingEnabled: Bool = true var customFont: CustomFont { return CustomFontManager.font(style: styleCategory) } func body(text content: Text) -> some View { let targetFont: Font if dynamicScalingEnabled { // 这里指定最大缩放对应的样式,比如你期望的XL级别对应.title1 targetFont = customFont.scaledFont(withMaxTextStyle: .title1) // 若需精确指定最大字号,改用: // targetFont = customFont.scaledFont(withMaxPointSize: 24) // 替换为你的目标最大字号 } else { targetFont = .custom(customFont.name, fixedSize: customFont.size) } return content .font(targetFont) .underline(customFont.underline) .lineSpacing((customFont.lineHeight / customFont.fontHeight) * customFont.fontHeight - customFont.fontHeight) } }
原理说明
UIFontMetrics会根据系统动态类型设置缩放字体,但maximumTextStyle或maximumPointSize参数会限制最大缩放程度,既保留了Dynamic Type的适配能力,又避免了超大文本设置下的容器溢出问题。
内容的提问来源于stack exchange,提问作者Anuj Rajput
相关产品推荐
相关产品推荐

