提问人:soundflix 提问时间:10/1/2023 最后编辑:soundflix 更新时间:10/7/2023 访问量:55
具有交替行颜色的多行文本(日志视图)。如何在所有行中选择文本?
Multiple lines of text with alternating row colors (a Log view). How to select text across all lines?
问:
我有一个日志视图。
我想以交替的背景颜色显示日志行。
我想允许在整个日志视图中选择文本。这可以在单个视图上完成。.textSelection(.enabled)
Text
然而,我的问题是,为了获得交替的背景颜色,我将字符串分成几行并将它们显示在(或)中。当我添加时,我一次只能选择一行中的文本。ScrollView
List
.textSelection(.enabled)
如何选择全文?
代码如下:
struct LogView: View {
let lines: [String] = sampleText3.components(separatedBy: "\n")
var body: some View {
ScrollView {
VStack(alignment: .leading, spacing: 0) {
ForEach(lines.indices, id: \.self) { index in
HStack() {
Text(lines[index])
.foregroundColor(adaptiveLineColor(lines[index]))
.padding(.horizontal, 5)
Spacer()
}
.background(index % 2 == 0 ? Color.gray.opacity(0.1) : Color.black.opacity(0.1))
}
}
.textSelection(.enabled)
.border(.gray.opacity(0.1),width: 1)
}
.padding()
}
func adaptiveLineColor(_ line: String) -> Color {
enum Tag: String {
case task = "[Task]"
case info = "[info]"
case warning = "[warning]"
case error = "[error]"
}
// TODO: Use switch
if line.hasPrefix(Tag.task.rawValue) {
return .green
}
if line.hasPrefix(Tag.info.rawValue) {
return .primary
}
if line.hasPrefix(Tag.warning.rawValue) {
return .yellow
}
if line.hasPrefix(Tag.error.rawValue) {
return .red
}
return .primary
}
}
let sampleText3: String = """
[Task] Process started. 30. Sep 2023, 21:26:20
[info] input file /someFolder/someData
[warning] invalid metadata
[error] error -1234
"""
截图:
如果我把整个文本放在一个多行中,可以按预期工作,但我不知道如何交替使用背景颜色。Text
textSelection
我该如何解决这个问题?
我找到了这个问题,但它没有解决方案。
答:
1赞
Sweeper
10/1/2023
#1
一个非常简单的解决方案(尽管这有点黑客)是绘制两次。首先将文本绘制为许多单独的 s,每个 s 都有自己的背景,并带有透明的前景。然后,将整个字符串绘制为单个作为叠加层。然后,用户可以选择叠加层。Text
Text
ScrollView {
let attrText = makeAttributedString(sampleText3) // add all the different foreground colors as an AttributedString
VStack(alignment: .leading, spacing: 0) {
// lay out the texts with transparent foreground and alternating backgrounds
let invisibleTexts = lines.map { Text($0).foregroundColor(.clear) }
ForEach(lines.indices, id: \.self) { index in
HStack {
invisibleTexts[index]
.padding(.horizontal, 5)
Spacer()
}
.background(index % 2 == 0 ? Color.gray.opacity(0.1) : Color.black.opacity(0.1))
}
}
.overlay {
// lay out the selectable text in the same way
HStack {
Text(attrText).textSelection(.enabled).padding(.horizontal, 5)
Spacer()
}
}
.border(.gray.opacity(0.1),width: 1)
}
评论
0赞
soundflix
10/1/2023
非常感谢,这有效!当你说它是黑客时,你认为它有缺点吗?
0赞
Sweeper
10/1/2023
@soundflix我正在创建许多不可见的 s,其唯一目的是显示背景颜色。这相当浪费,不是吗?“非黑客”是指 SwiftUI 有一个专用的 API 来将不同视图中的文本“连接”在一起。不过我不知道这样的事情。Text
0赞
soundflix
10/1/2023
好的,我明白了;对于较长的日志,我注意到调整窗口大小时性能下降。
0赞
soundflix
10/1/2023
我现在正在用一个真实的日志进行测试,他们有空行。这些似乎在叠加层上增加了偏移量。当我在覆盖层内部添加时,它会固定到第一个空行。然后,每条空线增加大约 1 个偏移点。.offset(y: -6)
0赞
Sweeper
10/1/2023
@soundflix嗯,我没想到会这样。我以为会具有与多行文本相同的布局。我建议首先尝试做并玩弄不起作用的属性字符串的行距。Text
VStack
VStack(spacing:0)
下一个:文本选择弹出菜单
评论
ShareLink