I have this code in Swift (iOS 16+) and I have a login screen into my app, where the user needs to enter an email and password.
I also have a .onTapGesture
method on the GeometryReader { ... }
wrapping everything together. I want the user to be able to dismiss the keyboard when tapping away from the text field.
But when the user enters an email and then wants to enter a password, the keyboard disappear and then appears again. How can I do that so the keyboard stays open (same expecting result as without the onTapGesture).
Here is my code
struct LoginView: View {
@Environment(\.horizontalSizeClass) var horizontalSizeClass
@State var email: String = ""
@State var password: String = ""
private let hapticFeedbackService = HapticFeedbackService()
var body: some View {
GeometryReader { screenGeometry in
let screenHeight = screenGeometry.size.height
ZStack {
Color.black.background.ignoresSafeArea(.all)
VStack {
WelcomeTextView(welcomeText: "sign_in_to")
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.top, screenHeight * 0.02)
VStack {
InputField(
text: $email,
placeholder: "enter_email",
isSecure: false
)
.padding(.bottom, 15)
InputField(
text: $password,
placeholder: "enter_password",
isSecure: true,
trailingIcon: Image("Lock")
)
}
Button(action: {
hapticFeedbackService.triggerHapticFeedback()
print("Button pressed")
}) {
Text(LocalizedStringKey("forgot_your_password"))
.font(.thinnerSmallTitle)
}
.padding(.top, 5)
.padding(.trailing, 5)
.frame(maxWidth: .infinity, alignment: .trailing)
LargeButton(
text: "sign_in",
textColor: Color.black,
backgroundColor: Color.white
) {
hapticFeedbackService.triggerHapticFeedback()
print("Button pressed")
}
.padding(.top, 40)
Text(LocalizedStringKey("other_login_options"))
.font(.mediumText)
.padding(.top, 10)
HStack {
SSOButton(type: .Apple, action: {
hapticFeedbackService.triggerHapticFeedback()
print("Button pressed")
})
.padding(.trailing, 5)
SSOButton(type: .Google, action: {
hapticFeedbackService.triggerHapticFeedback()
print("Button pressed")
})
.padding(.leading, 5)
}
.padding(.top, 10)
HStack {
Text(LocalizedStringKey("dont_have_account"))
.font(.mediumText)
.foregroundColor(Color.black)
Button(action: {
hapticFeedbackService.triggerHapticFeedback()
print("Button pressed")
}) {
Text(LocalizedStringKey("dont_have_account_sign_up"))
.font(.smallTitle)
.foregroundColor(Color.black)
}
}
.padding(.top, 25)
Spacer()
}
.paddedFrame(
screenSize: screenGeometry.size,
horizontalSizeClass: horizontalSizeClass
)
}
}
.ignoresSafeArea(.keyboard)
.onTapGesture { self.hideKeyboard() }
}
private func hideKeyboard() {
// UIApplication.shared.keyWindow?.endEditing(true) - Deprecated
UIApplication.shared.sendAction(
#selector(UIResponder.resignFirstResponder),
to: nil,
from: nil,
for: nil
)
}
}
Thank you.
One another solution is like
on your ZStack
ZStack {
Color.yellow.frame(maxWidth: .infinity, maxHeight: .infinity).onTapGesture {
hideKeyboard()
}
And at the bottom no need to give tap geture to your entire ZStack
ZStack {
//Your code
}
.ignoresSafeArea(.keyboard)
.onTapGesture { self.hideKeyboard() }
It should work.