SwiftUI 列表中的可编辑文本字段

问题描述 投票:0回答:5

更新:14 个月后,AppKit 发行说明中有一个有趣的注释:

您在选定列表行内编辑的文本字段现在具有正确的文本前景色。 (68545878)

现在,当将 TextField 放入列表中时,TextField 在第一次被选择时会在单击时获得焦点,但后续编辑尝试失败:列表行被选中,但 TextField 未获得焦点。

O/P:

在 beta6

SwiftUI
macOS(不是 iOS)应用程序中,我需要一个带有可编辑文本字段的
List
,但列表中的
TextField
不可编辑。如果我将
List
换成
Form
(或只是
VStack
),效果很好,但我需要它与
List
一起使用。有什么技巧可以告诉列表使字段可编辑吗?

import SwiftUI

struct ContentView: View {
    @State var stringField: String = ""

    var body: some View {
        List { // works if this is VStack or Form
            Section(header: Text("Form Header"), footer: Text("Form Footer")) {
                TextField("Line 1", text: $stringField).environment(\.isEnabled, true)
                TextField("Line 2", text: $stringField)
                TextField("Line 3", text: $stringField)
                TextField("Line 4", text: $stringField)
                TextField("Line 5", text: $stringField)
            }
        }
    }
}
swiftui appkit
5个回答
5
投票

错误报告

我更新了项目以针对 MacOS 应用程序,并发现了您报告的错误。我已向 Apple 更新了此反馈,因为它确实似乎是一个错误(欢迎使用 Beta)。

FB7174245 - 嵌入列表中的 SwiftUI 文本字段不可编辑 当目标是 macOS 时

更新

那么下面对状态和绑定的关注有什么意义呢?一个变量应该绑定到一个控件。这是一个工作示例。我将保留旧的答案,因为它通过完整的应用程序保存和检索 CoreData 的数据来推进示例。

import SwiftUI

struct ContentView: View {
    @State var field1: String = ""
    @State var field2: String = ""
    @State var field3: String = ""
    @State var field4: String = ""
    @State var field5: String = ""

    var body: some View {
        List { // works if this is VStack or Form
            Section(header: Text("Form Header"), footer: Text("Form Footer")) {
                TextField("Line 1", text: $field1).environment(\.isEnabled, true)
                TextField("Line 2", text: $field2)
                TextField("Line 3", text: $field3)
                TextField("Line 4", text: $field4)
                TextField("Line 5", text: $field5)
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

顺便说一句 - 这适用于 Xcode Beta (11M392r) 和 MacOS Catalina - 10.15 测试版(19A546d)。

示例项目

查看这个示例,其中包含一个可写入 CoreData 的可编辑文本字段,我正在 Github 上构建该文本字段。

看看@State和@Binding之间的区别,以便您 可以从内容视图外部操作数据。 (60 秒 视频

struct ContentView: View {
    // 1.
    @State var name: String = ""
    var body: some View {
        VStack {
            // 2.
            TextField(" Enter some text", text: $name)
                .border(Color.black)
            Text("Text entered:")
            // 3.
            Text("\(name)")
        }
        .padding()
        .font(.title)
    }
}

来源

查看以下答案以了解 @State 的适当用例 (所以回答


4
投票

以下代码只是一个实验,旨在了解 SwiftUI 中 List 的特性并展示替代方案。通过观察各种组合的输出,我了解到的是,列表视图的样式的结构方式是覆盖底层视图的默认行为,使其成为可选择的。这意味着 TextField 的作用完全不同。 TextField 是一个可聚焦的元素,我们可以在其中键入内容。此聚焦变量未连接到列表视图以协同工作。因此,列表会覆盖默认的可聚焦。因此不可能用 TextView 创建列表。但如果您需要,下一个最佳选择是 ScrollView 而不是 List,并显式地进行样式设置。检查以下代码以及两种方式。

import SwiftUI

struct ContentView: View {
    @State private var arr = ["1","2","3"]
    var body: some View {
        HStack {
            VStack {
                List {
                    ForEach(self.arr.indices, id:\.self) {
                        TextField("", text: self.$arr[$0])
                    }
                }
            }
            .frame(minWidth: 150, maxWidth: .infinity, minHeight: 300, maxHeight: .infinity)
            VStack {
                ScrollView {
                    ForEach(self.arr.indices, id:\.self) {
                        TextField("", text: self.$arr[$0])
                        .textFieldStyle(PlainTextFieldStyle())
                        .padding(2)
                    }
                }
                .padding(.leading, 5)
                .padding(3)
            }
            .background(Color(NSColor.alternatingContentBackgroundColors[0]))
            .frame(minWidth: 150, maxWidth: .infinity, minHeight: 300, maxHeight: .infinity)
        }
    }
}

extension NSTextField {
    open override var focusRingType: NSFocusRingType {
        get { .none }
        set { }
    }
}

1
投票

是否获得焦点 - 如果您点击正确

macOS 应用程序中使用 Xcode 12.4 和 SwiftUI 2,我似乎遇到了同样的问题:无法使 TextEdit 在列表中工作。阅读此处并进行更多实验后,我意识到在我的情况下,TextField 确实可靠地获得焦点,但仅当您以正确的方式点击时。我认为并希望这不是它应有的工作方式,因此我发布了问题 macOS 上 SwiftUI 中的列表中的 TextField:编辑效果不佳,解释了我观察到的详细信息。

总结:在现有文本上精确单击确实可以获得焦点(在短暂的、烦人的延迟之后)。双击任意位置不会获得焦点。单击空白字段中的任意位置确实会获得焦点。


0
投票

SwiftUI 2.0

您可以在列表中使用 TextEditor 代替 TextField 以获得可编辑的文本字段。

TextEditor(text: $strings)
    .font(.body)
    .cornerRadius(5)
    .shadow(color: Color.black.opacity(0.18), radius: 0.8, y: 1)
    .frame(height: 20)

这样您将在 TextEditor 和 TextField 之间获得相似的外观。


0
投票

放置在 SwiftUI

TextField
(启用选择)内的
List
macOS 13.5.1 开始似乎具有正确的编辑行为。当您单击选定的行时,
TextField
变为可编辑。剪辑的长文本的水平“滚动”也可以正常工作。这些功能在 macOS 12.6.8 上无法正常工作。

但是,

ContextMenu
的行为不正确。在选定的
TextField
上右键单击(例如,用两根手指点击触控板)不会调出附加到
TextField
(或
List
)的上下文菜单,而是错误地使
TextField
可编辑并带来在
TextField
内选择所选文本的系统文本选择菜单(例如查找、翻译、搜索、剪切、复制、粘贴、共享等)。按住 Control 键并单击
TextField
不会弹出任何菜单。相反,如果选择了
TextField
,则会将其置于编辑模式。如果按住 Control 键单击未选定的行/
TextField
,则会选择该
TextField
,而不是显示
ContextMenu

感觉从事 SwiftUI 的工程师对于 macOS 应该如何表现没有太多经验。

© www.soinside.com 2019 - 2024. All rights reserved.