SwiftUI中Google自定义字体文字截断及动态适配问题求解
SwiftUI自定义Google Fonts字符截断问题解决方案
问题概述
在SwiftUI中使用Google Fonts提供的Allura-Regular、Courgette-Regular、MrDafoe-Regular、ShadowsIntoLightTwo-Regular、SourceSansPro-Regular自定义字体时,带有高度的字符(如D、H、J、I等)出现截断情况。
已尝试的无效操作
- 设置
frame为maxWidth(.infinity)并调整高度 - 添加
padding及trailing方向内边距 - 使用
.fixedSize(horizontal: true, vertical: false)和.scaledToFit() - 新建空白SwiftUI项目测试问题仍然存在
关键观察
- 自定义字体以
UIFont形式应用于UIKit的UILabel时显示正常 - 以
SwiftUI.Font形式使用时出现字符截断 - 集成自定义
UILabelView(UIViewRepresentable)到SwiftUI代码中,问题依旧存在
需求
- 标签随字符数量增加动态调整字号
- 单行适配视图宽度
- 项目最低部署版本为iOS 15
解决方案
方案1:优化SwiftUI Text的配置
SwiftUI的Text对部分自定义字体的基线、 ascent/descent 计算存在偏差,可通过以下调整修复:
- 使用
.custom(_:size:relativeTo:)方法指定字体,帮助SwiftUI正确计算文本容器 - 添加垂直内边距预留字符高度空间
- 调整
minimumScaleFactor为合理值,确保缩放逻辑正常
修改后的SwiftUI代码片段:
HStack(spacing: 8) { Spacer() Text(signText) .lineLimit(1) .allowsTightening(true) .minimumScaleFactor(0.25) // 替换原.font(font),用custom方法并指定relativeTo参数 .font(.custom("Allura-Regular", size: 100, relativeTo: .title)) .padding(.vertical, 8) // 增加垂直内边距避免字符被截断 .frame(maxWidth: .infinity, alignment: .center) Spacer() if !signText.isEmpty { Button(action: { isSignSheetPresented = true }, label: { Image("edit") .renderingMode(.template) .frame(idealWidth: 44) .foregroundColor(Color(CanopyColor.primary.color)) }) } } .padding(16) .frame(maxWidth: .infinity, idealHeight: 150, alignment: .center ) .background(Color(red: 0.98, green: 0.98, blue: 0.98)) .cornerRadius(4) .overlay( RoundedRectangle(cornerRadius: 4) .inset(by: 0.5) .stroke(Color(red: 0.87, green: 0.87, blue: 0.87), lineWidth: 1) )
方案2:修复UIViewRepresentable的UILabel配置
原UILabelView添加了固定宽度约束,导致无法自适应父视图宽度,同时需要调整内容优先级确保布局正确:
修改后的UILabelView代码:
struct UILabelView: UIViewRepresentable { var text: String var font: UIFont func makeUIView(context: Context) -> UILabel { let label = UILabel() label.font = font label.text = text label.numberOfLines = 1 label.textAlignment = .center label.backgroundColor = .clear label.adjustsFontSizeToFitWidth = true label.minimumScaleFactor = 0.25 label.allowsDefaultTighteningForTruncation = true label.translatesAutoresizingMaskIntoConstraints = false // 移除固定宽度约束,设置内容优先级让label自适应父视图 label.setContentHuggingPriority(.defaultLow, for: .horizontal) label.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal) return label } func updateUIView(_ uiView: UILabel, context: Context) { uiView.text = text uiView.font = font uiView.textAlignment = .center } }
额外检查项
- 确认Info.plist中已添加
Fonts provided by application条目,且字体文件名与注册名完全一致 - 检查字体文件是否正确导入项目(勾选"Add to targets")
内容的提问来源于stack exchange,提问作者SwiftCoderJr
相关产品推荐
相关产品推荐

