'How can I remove Textfield focus when I press return or click outside Textfield? (SwiftUI, MacOS)
How can I remove Textfield focus when I press return or click outside Textfield? Note that this is SwiftUI on MacOS.
If I do this:
import SwiftUI
struct ContentView: View {
@State var field1: String = "This is the Text Field View"
var body: some View {
VStack{
Button("Press") {
print("Button Pressed")
}
TextField("Fill in Text", text: Binding(
get: { print("get") ; return self.field1 },
set: { print("set") ; self.field1 = $0 }
)
)
}
}
}
then click into the TextField and edit it then click on the Button the TextField does not lose focus. How can I make it exit editing mode and lose focus.
I would also like to lose focus from the TextField if I press Return. I used the Binding initialiser with get and set because I thought I could somehow intercept keypresses and detect the 'Return' character but this doesn't work.
Any help appreciated :-)
Solution 1:[1]
Here are possible variants
import SwiftUI
import AppKit
struct ContentView: View {
@State var field1: String = "This is the Text Field View"
var body: some View {
VStack{
Button("Press") {
print("Button Pressed")
NSApp.keyWindow?.makeFirstResponder(nil)
}
TextField("Fill in Text", text: Binding(
get: { print("get") ; return self.field1 },
set: { print("set") ; self.field1 = $0 }
), onCommit: {
DispatchQueue.main.async {
NSApp.keyWindow?.makeFirstResponder(nil)
}
}
)
}
}
}
Solution 2:[2]
Just add a onTapGesture
to your VStack
with the following line:
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to:nil, from:nil, for:nil)
This code will close the keyboard.
Example:
VStack {
// ...
}.onTapGesture {
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to:nil, from:nil, for:nil)
}
Solution 3:[3]
Based on the previous answers I have created a .removeFocusOnTap
extension that can be attached to any view that should remove the focus when tapped (I use it on the background view). It works for both iOS and macOS.
public struct RemoveFocusOnTapModifier: ViewModifier {
public func body(content: Content) -> some View {
content
#if os (iOS)
.onTapGesture {
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to:nil, from:nil, for:nil)
}
#elseif os(macOS)
.onTapGesture {
DispatchQueue.main.async {
NSApp.keyWindow?.makeFirstResponder(nil)
}
}
#endif
}
}
Extension:
extension View {
public func removeFocusOnTap() -> some View {
modifier(RemoveFocusOnTapModifier())
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Tobias Hesselink |
Solution 3 |