Reputation: 2277
How can I detect when a TextField is tapped? (SwiftUI on MacOS)
import SwiftUI
struct ContentView: View {
@State var field: String = "TextField"
var body: some View {
TextField("Fill in Text", text: $field)
.onTapGesture {
print("Textfield pressed")
}
}
}
When the TextField is tapped it doesn't print "Textfield pressed". I'm guessing this is because the tap is picked up by the TextField before it can be detected by the Textfield gesture.
Upvotes: 7
Views: 10934
Reputation: 258541
The .simultaneousGesture
modifier does what you need.
Here is an example:
struct TestTextTap: View {
@State var field: String = "TextField"
var body: some View {
TextField("Fill in Text", text: $field)
.simultaneousGesture(TapGesture().onEnded {
print("Textfield pressed")
})
}
}
Upvotes: 7
Reputation: 992
Unfortunately, .simultaneousGesture
did not work for me on macOS, but what worked was to use Introspect to get the NSTextField and add a NSClickGestureRecognizer
to it.
Then I added a @StateObject
to handle the target/action.
Upvotes: 1
Reputation: 120133
There is a new wrapper called @FocusState
that controls the state of the keyboard and the focused keyboard ('aka' firstResponder).
you can observe on the changes of the @FocusState
variable with .onChange
modifier
If you use a focused
modifier on the text fields, you can make them become focused, for example, you can set the focusedField
property in the code to make the binded textField become active:
or dismiss the keyboard by setting the variable to nil
:
Don't forget to watch the Direct and reflect focus in SwiftUI session from WWDC2021
Instead of Taping, You can detect when TextField
is focused easily inside onEditingChanged
:
TextField("Fill in Text", text: $field, onEditingChanged: { focused in
print(focused ? "focused" : "unfocused")
}
Upvotes: 8
Reputation: 105
I was able to get the intended results, but it feels slightly hacky until macOS can register a tap inside the text field.
I overlaid an almost transparent rectangle on top of the TextField. If the tap was sensed at that point, the TextField would not be selectable, but in SwiftUI you can make it the focus by using a @FocusState boolean.
So when the onTapGesture is sensed, it will change the @FocusState variable to true, which will let the user type into the TextField.
The little differences in macOS that make everything so much more complicated are maddening at times.
@State var field: String = "TextField"
@FocusState private var textFieldIsFocused: Bool
var body: some View {
TextField("Fill in Text", text: $field)
.focused($textFieldIsFocused)
.overlay((Color.white.opacity(0.0001)))
.onTapGesture {
self.textFieldIsFocused = true
print("Textfield pressed")
}
}
Sorry, edited because I realized I did not include the .focused method!
Upvotes: 3