SwiftUI日志视图:如何实现隔行变色且支持跨全选文本?
解决SwiftUI日志视图隔行变色+跨行文本选择的兼容问题
核心思路是使用AttributedString将所有日志行合并为一个富文本对象,既可以为每一行(段落)设置独立的背景色,又能保持单个Text视图的跨文本选择能力。
实现代码
import SwiftUI struct LogView: View { let lines: [String] = sampleText3.components(separatedBy: "\n") // 合并带格式的富文本 private var attributedLog: AttributedString { var fullAttributedString = AttributedString() for (index, line) in lines.enumerated() { var lineAttr = AttributedString(line) // 设置文字颜色 lineAttr.foregroundColor = adaptiveLineColor(line) // 设置隔行背景色 let backgroundColor = index % 2 == 0 ? Color.gray.opacity(0.1) : Color.black.opacity(0.1) lineAttr.backgroundColor = backgroundColor // 添加行内边距(模拟原布局的padding) lineAttr.padding(.horizontal, 5) fullAttributedString.append(lineAttr) // 每行末尾添加换行(最后一行省略多余空行) if index != lines.endIndex - 1 { fullAttributedString.append(AttributedString("\n")) } } return fullAttributedString } var body: some View { ScrollView { Text(attributedLog) .textSelection(.enabled) .border(.gray.opacity(0.1), width: 1) .padding() } .padding() } // 优化后的日志行颜色判断 func adaptiveLineColor(_ line: String) -> Color { enum Tag: String { case task = "[Task]" case info = "[info]" case warning = "[warning]" case error = "[error]" } guard let tag = Tag(rawValue: line.prefix(6).trimmingCharacters(in: .whitespaces)) else { return .primary } switch tag { case .task: return .green case .info: return .primary case .warning: return .yellow case .error: return .red } } } let sampleText3: String = """ [Task] Process started. 30. Sep 2023, 21:26:20 [info] input file /someFolder/someData [warning] invalid metadata [error] error -1234 """
关键说明
- AttributedString段落背景:给每一行对应的AttributedString设置
backgroundColor实现隔行变色,所有行合并为一个整体后,仍能支持跨文本选择。 - 保留原有样式:原有的文字颜色逻辑优化为switch语句,同时通过
padding属性模拟原布局的行内边距。 - 跨选能力生效:单个
Text视图承载全部内容,.textSelection(.enabled)可正常支持跨多行选择文本。
内容的提问来源于stack exchange,提问作者soundflix
相关产品推荐
相关产品推荐

