4

As far as I can tell, the only built in way to dismiss the keyboard from a TextField in SwiftUI is to press return. I would like to make it so I can tap somewhere on the screen other than the TextView and dismiss the keyboard. There is a way to do it like this:

var body: some View {
  VStack(alignment: .center, spacing: 0) {
    Text("some text")
      .frame(maxWidth: .infinity)
      .contentShape(Rectangle())
      .onTapGesture(
        // dismiss keyboard here
      )

    TextField("text", $binding)

    Text("more text")
      .frame(maxWidth: .infinity)
      .contentShape(Rectangle())
      .onTapGesture(
        // dismiss keyboard here
      )
  }                  
}

That is a bit cumbersome. I would like to do it this way:

var body: some View {
  VStack(alignment: .center, spacing: 0) {
    Text("some text")

    TextField("text", $binding)

    Text("more text")
  } 
  .frame(maxWidth: .infinity)
  .contentShape(Rectangle())
  .onTapGesture(
    // dismiss keyboard here
  )          
}

This works for the most part, but the gesture on the outermost view overrides the gesture of the textfield. When you first press on the textfield the keyboard displays, but when you press it again it dismisses which I don't want. I want the subview gestures to take precedence. If there is a button in the VStack, it should register just the button and not the dismiss gesture. I was looking into GestureMask and ExclusiveGesture but I couldn't find a way. Is there a way anyone knows of?

Steve Frazee
  • 173
  • 1
  • 7
  • This might help you: [How to hide keyboard when using SwiftUI?](https://stackoverflow.com/a/60010955/8697793) – pawello2222 Sep 15 '20 at 22:12
  • I appreciate the link, but unfortunately I could not find an answer there that does not break some of my other subview gestures. – Steve Frazee Sep 15 '20 at 22:24
  • Did you try the specific answer I linked to? – pawello2222 Sep 15 '20 at 22:46
  • Yes I did and I realize I wasn't clear enough in my original question. That solution almost works. If there is a subview with a tap gesture then I want that to register and not the dismiss gesture. In that solution, both of the taps register and not just the subview. I edited my original question to hopefully be more clear. – Steve Frazee Sep 15 '20 at 23:39

1 Answers1

7

We can use simultaneousGesture. It will work without blocking any other subviews gestures.

Example

Vstack{
   other subview gestures
}.simultaneousGesture(
    TapGesture()
    .onEnded { _ in
        print("VStack tapped")
    }
)
Leo ananth
  • 141
  • 2
  • 5