I implemented a y-offset mechanism for my TextField
when the keyboard is visible. On tap, the entire screen is moved up. Now, I want to tap on any empty space to dismiss the keyboard. The problem is that the added space granted by the offset does not receive my tap gesture.
struct LoginView: View {
@State private var email = ""
@State private var password = ""
@State private var keyboardYOffset = CGFloat(0)
var body: some View {
VStack {
VStack(spacing: 32) {
Rectangle()
.frame(width: 187, height: 208)
.padding(.top, 56)
.padding(.bottom, 94)
.background(Color.red)
TextField("Email", text: $email)
.frame(maxWidth: .infinity)
.frame(height: 50)
// inset of the placeholder text
.padding(.horizontal)
.border(Color.red)
// inset of the entire textfield
.padding(.horizontal)
SecureField("Password", text: $email)
.frame(maxWidth: .infinity)
.frame(height: 50)
// inset of the placeholder text
.padding(.horizontal)
.border(Color.red)
// inset of the entire textfield
.padding(.horizontal)
Spacer()
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.padding(.top, 32)
.background(Color.white.ignoresSafeArea())
}
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top)
.background(Theme.BrandColor.primary.ignoresSafeArea())
.offset(y: -keyboardYOffset)
.animation(.easeInOut(duration: 1), value: keyboardYOffset)
.onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardWillShowNotification)) { notification in
let value = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect
let keyboardHeight = value?.height ?? 0
// for our purposes we only need to offset by half the keyboard height
self.keyboardYOffset = keyboardHeight / 2
}
.onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardWillHideNotification)) { _ in
self.keyboardYOffset = 0
}
.onTapGesture {
UIApplication.shared.endEditing()
}
}
}
struct LoginView_Previews: PreviewProvider {
static var previews: some View {
LoginView()
}
}
extension UIApplication {
func endEditing() {
sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
}
}
I’ve tried adding a tap gesture recogniser everywhere to no avail.
2
Answers
fixed it by adding a contentShape modifier to the outermost VStack
Try this: