14

So basically I created a multiline textField, but pressing onSubmit won't work at all, I rather it submit when double pressing return or something similar. if there is a way to avoid collapsing the keyboard when submitting instead of using multiline I would be grateful to be told how :)

2 Answers2

8

This is the workaround that I've used:

struct SwiftUIView: View {
    
    @State var text: String = ""
    
    var body: some View {
        TextField("text", text: $text, axis: .vertical)
            .frame(width: 200, height: 200)
            .multilineTextAlignment(.leading)
            .textFieldStyle(.roundedBorder)
            .font(.title)
            .onChange(of: text) { newValue in
                guard let newValueLastChar = newValue.last else { return }
                if newValueLastChar == "\n" {
                    text.removeLast()
                    hideKeyboard()
                }
            }
    }
}

Being hideKeyboard a function defined in an extension of View:

extension View {
    func hideKeyboard() {
        UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
    }
}
tecosabri
  • 81
  • 4
0

In my case I wanted the tab key to work so that the next field is focusses when the user presses tab. That works out of the box when using TextField("User name (email address)", text: $username), but it stops working when using , axis: ....

This workaround fixes it for me. It compares the old value with the new, ensuring that (a) the string grew by just one character and (b) that the new string has one \t more than the old string. That ensures that the user can tab anywhere in the field and should offer reasonable protection when the user pastes texts into the field that could contain tab characters.

TextField("Title", text: $title, axis: .vertical)
    .focused($focus, equals: .title)
    .onChange(of: title) { [title] newValue in
        let oldTabCount = title.filter { $0 == "\t" }.count
        let newTabCount = newValue.filter { $0 == "\t" }.count
        
        if newValue.count == (title.count + 1) && newTabCount == (oldTabCount + 1) {
            // Reset title to previous value (without the new tab)
            self.title = title
            self.focus = .content
        }
    }

TextField("Content", text: $content)
    .focused($focus, equals: .content)

The focus var is defined as @FocusState var focus: FocusOption? and FocusOption is a simple enum:

enum FocusOption: Equatable {
   case title
   case content
}

Enjoy!

Johannes Fahrenkrug
  • 42,912
  • 19
  • 126
  • 165