SwiftUI 怎么输入多行文本

175 阅读2分钟

这个问题可能有点扯。多行文本就用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 将会触发。但这显然是不对的。