skip to Main Content

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) - Depricated
        
        UIApplication.shared.sendAction(
            #selector(UIResponder.resignFirstResponder),
            to: nil,
            from: nil,
            for: nil
        )
    }
}

Thank you.

2

Answers


  1. You shouldn’t put close keyboard action to the whole view. Beause it will dismiss the keyboard when you click anywhere. And the reason its reappearing is textfield realizing its on edit mode after the keyboard dismisses.

    struct MyView: 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)
                    .onTapGesture { self.hideKeyboard() }
                    
                    VStack {
                        WelcomeTextView(welcomeText: "sign_in_to")
                            .frame(maxWidth: .infinity, alignment: .leading)
                            .padding(.top, screenHeight * 0.02)
                            .onTapGesture { self.hideKeyboard() }
                        
                        VStack {
                            InputField(
                                text: $email,
                                placeholder: "enter_email",
                                isSecure: false
                            )
                            .padding(.bottom, 15)
                            
                            InputField(
                                text: $password,
                                placeholder: "enter_password",
                                isSecure: true,
                                trailingIcon: Image("Lock")
                            )
                        }
                        
                        Group {
                            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)
                        }
                        .onTapGesture { self.hideKeyboard() }
                        
                        Spacer()
                    }
                    .paddedFrame(
                        screenSize: screenGeometry.size,
                        horizontalSizeClass: horizontalSizeClass
                    )
                }
            }
            .ignoresSafeArea(.keyboard)
        }
    
        private func hideKeyboard() {
            // UIApplication.shared.keyWindow?.endEditing(true) - Depricated
            
            UIApplication.shared.sendAction(
                #selector(UIResponder.resignFirstResponder),
                to: nil,
                from: nil,
                for: nil
            )
        }
    }
    
    Login or Signup to reply.
  2. To help you better, could you please provide specific issue you are facing with your Swift code? Are you encountering any other errors, or do you need only assistance with a particular aspect of the login screen implementation, like form validation, networking, or user interface design? Let me know so I can provide you with the most relevant assistance.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search