iOS 15中如何让本地化字符串指定部分文本显示为粗体?
问题
在SwiftUI视图里展示文本时,想让部分文本用不同字体。我的Localizable文件里有这么个本地化字符串:
"unencrypted_emails_header" = "we may send you **business email unencrypted** and that you assume the risks"
目标是让**包裹的内容显示为粗体。
最开始试了这段代码:
Text(headerText()) .rchFont(.rchBody) private func headerText() -> String { let rchBodyFont = RCHFont.rchBody let rchBodyBoldFont = RCHFont.rchBodyBold let headerString = strings.unencryptedEmailsHeader.replacingOccurrences(of: "**", with: "") let attributedString = NSMutableAttributedString(string: headerString) if let range = headerString.range(of: #"(?<=\*\*)(.*?)(?=\*\*)"#, options: .regularExpression) { let nsRange = NSRange(range, in: headerString) attributedString.addAttribute(.font, value: rchBodyBoldFont, range: nsRange) } return attributedString.string }
结果是**确实被移除了,但对应文本并没有变成粗体。项目最低支持iOS 15。
后来又改了写法:
Text(LocalizedStringKey(strings.unencryptedEmailsHeader)) .rchFont(.rchBody)
不加.rchFont(.rchBody)的时候粗体是生效的,但一加这个自定义字体修饰符,粗体就被覆盖了,显示不出来。
解决方案
方法一:用AttributedString解析Markdown并适配自定义字体
iOS 15已经支持AttributedString的Markdown解析,我们可以先把本地化字符串转成带样式的AttributedString,再给不同样式的文本段分配对应的自定义字体:
// 视图中直接使用 Text(try! AttributedString(markdown: strings.unencryptedEmailsHeader) .applyCustomFonts(body: RCHFont.rchBody, boldBody: RCHFont.rchBodyBold))
然后给AttributedString加个扩展方法来处理字体替换:
extension AttributedString { func applyCustomFonts(body: UIFont, boldBody: UIFont) -> AttributedString { var mutableString = self // 遍历每个文本片段,根据粗体属性分配对应字体 for run in mutableString.runs { if run.fontProperties?.weight == .bold { mutableString[run.range].font = boldBody } else { mutableString[run.range].font = body } } return mutableString } }
这个思路是先通过Markdown解析保留粗体标记,再把默认的粗体/常规字体替换成你自定义的字体,既保留了样式,又用上了自定义字体。
方法二:修改自定义字体修饰符的实现
如果你的.rchFont是自己写的ViewModifier,可以调整它的逻辑,让它尊重文本原有的粗体权重:
extension View { func rchFont(_ style: RCHFont) -> some View { self.modifier(RCHFontModifier(style: style)) } } struct RCHFontModifier: ViewModifier { let style: RCHFont func body(content: Content) -> some View { content // 这里不要直接覆盖整个字体,而是结合原有权重处理 .font(Font(style.font)) .fontWeight(style == .rchBodyBold ? .bold : .regular) } }
不过这种方式只适合简单场景,如果文本是通过LocalizedStringKey生成的多样式文本,还是方法一的AttributedString处理更准确。
方法三:拆分文本组合(仅适合固定结构的文本)
如果你的本地化字符串结构不会随语言变化,可以直接拆分文本分别设置字体再组合:
Text(strings.unencryptedEmailsPrefix) .font(Font(RCHFont.rchBody)) + Text(strings.unencryptedEmailsBoldPart) .font(Font(RCHFont.rchBodyBold)) + Text(strings.unencryptedEmailsSuffix) .font(Font(RCHFont.rchBody))
但这种方式不推荐用于本地化场景,因为不同语言的语序可能完全不同,拆分后容易出问题。
内容的提问来源于stack exchange,提问作者user20273483
相关产品推荐
相关产品推荐

