这个问题可能有点扯。多行文本就用TextEditor。就像 UIKit 中多行文本用 UITextView。
但实际却未必,尤其是,如果多行文本前再多一个限定:自增。
UIKit 多行文本的输入确实只能用 UITextView (几年没用 UIKit,不确定自己有没记错,但应该是这样),不过能,SwiftUI 可不是只有 TextEditor 一个选择。
在 SwiftUI 中,使用 TextField 也可以进行多行文本输入。使用场景,当你需要轻量级的多行文本输入,并且能自增高度的时候,就可以使用 TextField。
比如在 Form 或者 List、 ScrollView 中,用 TextField 就比用 TextEditor 更加合适。
这些视图自身就有滚动功能,如果用 TextEditor,二者的滚动就会有冲突。并且,TextEditor 应该给多少高度合适呢?
这一切的限制,都表明 TextField 在这种情况下是更好的选择。
并且 Form 中用到多行文本的情况应该不会进行大段的文本输入。
怎么用 TextField 来实现多行自增文本的功能呢?
#Preview {
@Previewable @State **var** text = ""
TextField("请输入多行文本", text: $text, axis: .vertical)
.onSubmit {
text += "\n"
}
}
下面看看怎么用在实际的项目中。直接上最终代码。
**struct** **ContentView**: **View** {
@State **private** **var** text = ""
@FocusState **private** **var** focused: Bool
**var** body: some View {
Form {
TextField("文本", text: $text, prompt: Text("文本"), axis: .vertical)
.focused($focused)
.onSubmit {
text += "\n"
focused = true
}
.submitScope()
.submitLabel(.**return**)
}
.onSubmit {
print("Submit")
}
}
}
解释一下。这里直接在 Form 中添加自增多行文本。在 VStack、List、ScrollView 等组件里同样适用。
给 TextField 添加 axist: .vertical,使 TextField 成为可以输入多行文本的视图。
但是,正常情况下,TextField 在输入时,点击换行,会触发 submit 功能。这时 TextField 会失去输入焦点,并且也不会换行。
.onSubmit {
text += "\n"
focused = true
}
onSubmit 添加换行的逻辑,给text添加'\n',同时 focused = true,保证 TextField 仍处于输入焦点,不会收起键盘。
在某些情况下,不需要 focused = true,TextField 仍会保持输入焦点,但为了避免有些点换行会导致焦点失效的情况,还是把这行代码加上。
submitScope() 则是拦截 submit 事件,不要再往上传递。如果没有这行代码,点换行的时候 Form 的 onSubmit 将会触发。但这显然是不对的。