2

In SwiftUI, TextField("", text: $input) has this automatic behavior, when you press done, the keyboard is dismissed. This is exactly what I wanted with the done button.

However, if you use TextField("", text: $input, axis: .vertical) the done button will become line change instead, and will no longer dismiss the keyboard.

I need scrollable TextField as TextField("", text: $input, axis: .vertical). At the same time, pressing done button to dismiss the keyboard instead of line change. Does anyone knows how to achieve it? Thank you!

enter image description here

Legolas Wang
  • 1,951
  • 1
  • 13
  • 26
  • Does this answer your question? [How to hide keyboard when using SwiftUI?](https://stackoverflow.com/questions/56491386/how-to-hide-keyboard-when-using-swiftui) – Arnab Jan 03 '23 at 08:26
  • 2
    Not really. Both onSubmit and @FocusState are not working, if added axis. It appears to be a bug in SwiftUI. – Legolas Wang Jan 03 '23 at 08:48

2 Answers2

2

I think you have to add one button above the keyboard which is called Tool bar button

Hope this will help

struct ContentView: View {
private enum Field: Int, CaseIterable {
    case username
}

@State private var username: String = ""

@FocusState private var focusedField: Field?

var body: some View {
    NavigationView {
            TextField("Username", text: $username)
                .focused($focusedField, equals: .username)
        .toolbar {
            ToolbarItem(placement: .keyboard) {
                Button("Done") {
                    focusedField = nil
                }
            }
        }
    }
}}
Hetali Adhia
  • 506
  • 3
  • 13
2

It appears .onSubmit doesn't get called either, so it definitely seems like a bug. E.g. this will never print.

TextField("", text: $text, axis: .vertical)
    .onSubmit {
        print("Test")
    }
    .submitLabel(.done)

I filed a feedback, but in the meantime this binding approach seems to work. It relies on monitoring the keypresses for a return and intercepting it. It's ok if you absolutely need it but you can sometimes notice a slight delay. Copying answer below.

struct ContentView: View {

    @State var message: String = ""
    @FocusState private var isFocused: Bool
    
    var body: some View {
        VStack {
            TextField("Placeholder",
                      text: Binding(
                        get: { message },
                        set:
                            { (newValue, _) in
                                if let _ = newValue.lastIndex(of: "\n") {
                                    isFocused = false
                                } else {
                                    message = newValue
                                }
                            }
                      ), axis: .vertical)
                .submitLabel(.done)
                .focused($isFocused)
        }
    }
}
JBZic
  • 53
  • 6
  • Please split the second part of your answer into another question. If you don’t you are turning your answer into a low quality post and you are being flagged for it. – jvarela Jul 06 '23 at 04:43
  • @jvarela I reformatted it instead, is that good? I didn't have a question on the first part as it's obviously related to the bug the original question asked about. I think it's valuable context and may help someone find a better answer in the future. – JBZic Jul 07 '23 at 05:45
  • Seems better now. – jvarela Jul 08 '23 at 14:40