SwiftUI中如何为垂直方向的TextField使用.onSubmit()方法?
解决SwiftUI垂直扩展TextField软键盘发送按钮不触发onSubmit的问题
在iOS 16+中使用TextField(_:text:axis:)创建可垂直扩展的多行文本框,设置.submitLabel(.send)后,软键盘的蓝色“发送”按钮仅会插入换行符,无法触发.onSubmit回调;但硬件键盘按下回车键却能正常触发。这是因为垂直模式下的TextField底层对应UITextView,其默认行为是将return键作为换行输入。
解决方案:自定义多行文本框封装
通过封装UITextView实现自定义提交逻辑,同时保留垂直扩展和原生输入体验:
import SwiftUI struct MultilineTextField: UIViewRepresentable { @Binding var text: String var placeholder: String var onSubmit: () -> Void func makeUIView(context: Context) -> UITextView { let textView = UITextView() textView.font = UIFont.systemFont(ofSize: 16) textView.textColor = .label textView.returnKeyType = .send textView.delegate = context.coordinator textView.text = placeholder textView.textColor = .placeholderText textView.backgroundColor = .clear // 适配SwiftUI背景样式 return textView } func updateUIView(_ uiView: UITextView, context: Context) { if uiView.text != text && !(text.isEmpty && uiView.text == placeholder) { uiView.text = text.isEmpty ? placeholder : text uiView.textColor = text.isEmpty ? .placeholderText : .label } } func makeCoordinator() -> Coordinator { Coordinator(parent: self) } class Coordinator: NSObject, UITextViewDelegate { let parent: MultilineTextField init(parent: MultilineTextField) { self.parent = parent } func textViewDidBeginEditing(_ textView: UITextView) { if textView.text == parent.placeholder { textView.text = "" textView.textColor = .label } } func textViewDidEndEditing(_ textView: UITextView) { parent.text = textView.text.trimmingCharacters(in: .whitespacesAndNewlines) if parent.text.isEmpty { textView.text = parent.placeholder textView.textColor = .placeholderText } } func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { // 拦截发送按钮点击事件,触发提交逻辑 if text == "\n" { parent.onSubmit() textView.resignFirstResponder() // 可选:提交后自动收起键盘 return false } return true } } } // 使用示例 struct ContentView: View { @State var message: String = "" var body: some View { VStack(spacing: 16) { Text("点击软键盘的发送按钮提交内容") .font(.subheadline) .foregroundColor(.secondary) MultilineTextField(text: $message, placeholder: "输入消息...", onSubmit: { guard !message.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty else { return } print("提交成功!内容:\(message)") message = "" // 提交后清空输入框 }) .frame(minHeight: 80, maxHeight: .infinity) .padding(.horizontal, 12) .padding(.vertical, 8) .border(Color.gray.opacity(0.3), cornerRadius: 8) } .padding() } }
说明
- 自定义文本框保留了原生垂直扩展特性,同时将软键盘“发送”按钮绑定到提交回调
- 硬件键盘可通过
Shift + Enter实现换行,若需调整换行逻辑,可修改shouldChangeTextIn方法的判断条件 - 内置占位符处理逻辑,与原生TextField体验一致
内容的提问来源于stack exchange,提问作者Android KitKat
相关产品推荐
相关产品推荐

