You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI中如何为TextEditor内的单个单词修改背景颜色

SwiftUI 实现TextEditor单个单词自定义背景色

效果示例图

原生SwiftUI TextEditor 没有提供局部文本样式自定义的公开API,要实现单词级背景高亮,需要封装底层的UITextView(iOS)/NSTextView(macOS),通过TextKit的属性字符串能力给指定单词添加背景属性,以下是Swift 5下可直接运行的实现:

iOS端实现代码

import SwiftUI

struct HighlightTextEditor: UIViewRepresentable {
    @Binding var text: String
    ///  key: 需要高亮的单词,value: 对应背景色
    let highlightRule: [String: UIColor]
    
    func makeUIView(context: Context) -> UITextView {
        let textView = UITextView()
        textView.font = .systemFont(ofSize: 16)
        textView.delegate = context.coordinator
        return textView
    }
    
    func updateUIView(_ textView: UITextView, context: Context) {
        // 记录光标位置,避免输入时光标跳转到末尾
        let cursorPosition = textView.selectedRange
        let totalLength = text.utf16.count
        
        let attrStr = NSMutableAttributedString(string: text)
        // 设置全局默认文本样式
        attrStr.addAttributes([
            .font: UIFont.systemFont(ofSize: 16),
            .foregroundColor: UIColor.label
        ], range: NSRange(location: 0, length: totalLength))
        
        // 遍历所有高亮规则,匹配单词位置
        for (word, bgColor) in highlightRule {
            let escapedWord = NSRegularExpression.escapedPattern(for: word)
            guard let regex = try? NSRegularExpression(pattern: "\\b\(escapedWord)\\b", options: .caseInsensitive) else { continue }
            let matches = regex.matches(in: text, range: NSRange(location: 0, length: totalLength))
            matches.forEach { match in
                attrStr.addAttribute(.backgroundColor, value: bgColor, range: match.range)
            }
        }
        
        textView.attributedText = attrStr
        // 恢复光标位置
        textView.selectedRange = cursorPosition
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(parent: self)
    }
    
    class Coordinator: NSObject, UITextViewDelegate {
        let parent: HighlightTextEditor
        init(parent: HighlightTextEditor) {
            self.parent = parent
        }
        
        func textViewDidChange(_ textView: UITextView) {
            parent.text = textView.text
        }
    }
}

// 调用示例
struct DemoView: View {
    @State private var content = "This is a sample text, we will highlight sample and text words with different background colors."
    private let highlightConfig = [
        "sample": UIColor.yellow.withAlphaComponent(0.4),
        "text": UIColor.systemBlue.withAlphaComponent(0.3)
    ]
    
    var body: some View {
        HighlightTextEditor(text: $content, highlightRule: highlightConfig)
            .padding()
    }
}

适配说明

  • macOS端适配:将UIViewRepresentable替换为NSViewRepresentable,UITextView替换为NSTextView,对应代理方法切换为NSTextViewDelegate的实现,核心的属性字符串高亮逻辑无需修改。
  • 匹配规则:代码中使用\b单词边界做正则匹配,只会匹配完整独立单词,不会误匹配单词中包含的子串,如果需要模糊匹配可以自行修改正则规则。
  • 如果需要实现圆角效果的背景高亮,无法直接通过属性字符串完成,需要自定义NSLayoutManager重写背景绘制逻辑。

内容的提问来源于stack exchange,提问作者Thomas FONTAINE

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 07:37:29