SwiftUI中NSMutableParagraphStyle段落样式不生效问题及解决
问题描述
我需要给包含阿拉伯语和英语的混合文本添加富文本属性:通过NSMutableAttributedString修改阿拉伯语部分的颜色、字体,同时用NSMutableParagraphStyle设置右对齐、行间距等段落样式。目前阿拉伯语的颜色修改已生效,但段落样式在SwiftUI的Text组件中完全不生效,不过相同的富文本在UIKit的UITextView里能正常显示所有样式。
相关代码如下:
富文本样式处理代码
let arabicChars = try? NSRegularExpression(pattern: "[\\u0600-\\u06FF\\u0750-\\u077F\\u08A0-\\u08FF\\uFB50-\\uFDFF\\uFE70-\\uFEFF\\s]+", options: []) arabicChars?.enumerateMatches(in: pureText, options: [], range: range) { (result, _, _) in if let subStringRange = result?.range(at: 0) { stringText.addAttribute(.foregroundColor, value: UIColor(.brown), range: subStringRange) let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.alignment = .right paragraphStyle.lineSpacing = 1.2 paragraphStyle.lineHeightMultiple = 1.2 stringText.addAttribute(.paragraphStyle, value: paragraphStyle, range: subStringRange) stringText.addAttribute(.font, value: UIFont(name: "CustomFont", size: 16)!, range: subStringRange) } }
SwiftUI调用代码
var body: some View { ScrollView { VStack(alignment: .leading, spacing: 15) { Text(word.word?.capitalized ?? "") .font(.system(size: 32, weight: .bold, design: .serif)) Text(AttributedString(applyAttributedStyle(word.meaning))) } .frame(maxWidth: .infinity, alignment: .leading) } .padding(.horizontal) }
原因分析
SwiftUI的Text组件对AttributedString的段落样式支持存在局限性,尤其是针对局部文本的段落样式设置。它仅能识别字体、颜色这类基础属性,无法像UIKit的UITextView那样完整解析并应用NSMutableParagraphStyle中的对齐、行间距等高级段落属性。
解决方案
通过UIViewRepresentable封装UIKit的UITextView,利用UIKit对富文本的完整支持来显示带段落样式的混合文本。
封装UITextView组件
struct AttributedTextView: UIViewRepresentable { var attributedString: NSAttributedString func makeUIView(context: Context) -> UITextView { let textView = UITextView() textView.isEditable = false textView.isScrollEnabled = false textView.backgroundColor = .clear return textView } func updateUIView(_ uiView: UITextView, context: Context) { uiView.attributedText = attributedString } }
替换SwiftUI中的Text组件
把原代码里的Text(AttributedString(...))替换为封装好的组件:
var body: some View { ScrollView { VStack(alignment: .leading, spacing: 15) { Text(word.word?.capitalized ?? "") .font(.system(size: 32, weight: .bold, design: .serif)) AttributedTextView(attributedString: applyAttributedStyle(word.meaning)) } .frame(maxWidth: .infinity, alignment: .leading) } .padding(.horizontal) }
这样就能完整显示包含段落样式的阿拉伯语和英语混合文本了。
内容的提问来源于stack exchange,提问作者Mc.Lover
相关产品推荐
相关产品推荐

