TextField 在放入多行时无法关闭键盘

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

TextField
这样创建时

 TextField(
            "Describe...",
            text: $text,
            axis: .vertical
        )
        .focused(focused, equals: .prompt)
        .textFieldStyle(.roundedBorder)
        .lineLimit(2...)
        .modifier(ClearButton(text: $text))
        .submitLabel(.done)
        .onSubmit { hideKeyboard()
            print("test")
        }

当按下键盘完成按钮时,它会创建一个新行。我根本不想在

TextField
中添加任何新行。

.submitLabel
应该可以做到。所以我添加了,但没有。

接下来我尝试创建一个

.onSubmit
回调,但这也不起作用。事实上,“test”永远不会被打印出来。

swift swiftui textfield
2个回答
2
投票

不是因为textField的多行,而是因为轴的原因。如果您删除行限制,问题仍然存在,但如果您更改轴,文本字段现在“有效”(它不是多行)。如果您使用

TextEditor
,也会发生同样的情况。但是,如果您想要一个能够关闭键盘的多行文本字段,则用户友好的解决方案可以是添加工具栏。现在,用户将把文本字段解释为多行文本字段(因为返回按钮),并且可以选择禁用文本字段。

struct TestView: View {
    
    enum Field {
        case prompt
    }
    
    @FocusState var focus: Field?
    @State var text = ""
    var body: some View {
        VStack {
                TextField(
                    "Describe...",
                    text: $text,
                    axis: .vertical
                )
                .focused($focus, equals: .prompt)
                .textFieldStyle(.roundedBorder)
                .lineLimit(2...)
                .submitLabel(.return) // <- change to return
                .toolbar { // adding the toolbar
                    ToolbarItemGroup(placement: .keyboard) {
                            Spacer()
                            Button("Done") {
                                focus = nil
                            }
                    }
                }
           
        }
       
    }
}

0
投票

我写了一篇短文,介绍如何使用

FocusState
onChange
来模拟多行中的返回键按下
TextField
TextEditor
:

struct MyView: View {

    @State
    var text = ""

    @FocusState
    var isFocused: Bool

    var body: some View {
        TextField("Enter text", text: $text, axis: .vertical)
            .submitLabel(.done)
            .focused($isFocused)
            .onChange(of: text) { newValue in
                guard isFocused else { return }
                guard newValue.contains("\n") else { return }
                isFocused = false
                text = newValue.replacing("\n", with: "")
            }
    }
}

您可以将这些修饰符提取到自定义

ViewModifier
中,以便于重用它:

struct MultilineSubmitViewModifier: ViewModifier {
    
    init(
        text: Binding<String>,
        submitLabel: SubmitLabel,
        onSubmit: @escaping () -> Void
    ) {
        self._text = text
        self.submitLabel = submitLabel
        self.onSubmit = onSubmit
    }
    
    @Binding
    private var text: String
    private let submitLabel: SubmitLabel
    private let onSubmit: () -> Void
    
    @FocusState
    private var isFocused: Bool
    
    func body(content: Content) -> some View {
        content
            .focused($isFocused)
            .submitLabel(submitLabel)
            .onChange(of: text) { newValue in
                guard isFocused else { return }
                guard newValue.contains("\n") else { return }
                isFocused = false
                text = newValue.replacingOccurrences(of: "\n", with: "")
                onSubmit()
            }
    }
}

您还可以创建自定义视图扩展以使其更易于使用:

public extension View {
    
    func onMultilineSubmit(
        in text: Binding<String>,
        submitLabel: SubmitLabel = .done,
        action: @escaping () -> Void
    ) -> some View {
        self.modifier(
            MultilineSubmitViewModifier(
                text: text,
                submitLabel: submitLabel,
                onSubmit: action
            )
        )
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.