skip to Main Content

Currently, I am hiding the keyboard when the user taps anywhere. I want to exclude 2 TextFields tap to avoid the keyboard hide/show effect.

import SwiftUI

struct ContentView: View {

    @FocusState var focus:FocusedField?
    @State var name = ""
    @State var email = ""
    @State var phoneNumber = ""

    var body: some View {
        List {
            TextField("Name:",text: $name)
                .focused($focus, equals: .name)
                .onSubmit {
                    focus = .email
                }
            TextField("Email:",text: $email)
                .focused($focus, equals: .email)
                .onSubmit {
                    focus = .phone
                }
            TextField("PhoneNumber:", text: $phoneNumber)
                .focused($focus, equals: .phone)
                .onSubmit {
                    if !name.isEmpty && !email.isEmpty && !phoneNumber.isEmpty {
                        submit()
                    }
                }
        }
        .onTapGesture {
            if (focus != nil) {
                hideKeyboard()
            }
        }
    }

    private func submit() {
        print("submit")
    }
    
    enum FocusedField: Hashable {
        case name, email, phone
    }
}

extension View {
    func hideKeyboard() {
        print("hideKeyboard")
        let resign = #selector(UIResponder.resignFirstResponder)
        UIApplication.shared.sendAction(resign, to: nil, from: nil, for: nil)
    }
}

I want:

  1. A stable keyboard for my TextFields with no hide and show effects.
  2. Tap anywhere to dismiss/hide the keyboard.

Please see the following effects:

enter image description here

2

Answers


  1. Chosen as BEST ANSWER

    I found the answer.

    public struct TapToHideKeyboardView: View {
        
        public init() {
        }
        
        public var body: some View {
            Button(action: {
                self.hideKeyboard()
            }) {
                Rectangle().foregroundColor(.brown)
            }
            .background(
                GeometryReader { geometry in
                    Color.clear
                        .frame(width: geometry.size.width, height: geometry.size.height)
                }
                    .onTapGesture {
                        self.hideKeyboard()
                    }
            )
        }
        
        func hideKeyboard() {
            UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
        }
    }
    

    Use this public struct inside Zstack.

    var body: some View{
            NavigationStack{
                ZStack {
                    TapToHideKeyboardView()
                    VStack{
                        TextField("Name:",text:$name)
                            .focused($focus, equals: .name)
                            .onSubmit {
                                focus = .email
                            }
                        TextField("Email:",text:$email)
                            .focused($focus,equals: .email)
                            .onSubmit {
                                focus = .phone
                            }
                        TextField("PhoneNumber:",text:$phoneNumber)
                            .focused($focus, equals: .phone)
                            .onSubmit {
                                if !name.isEmpty && !email.isEmpty && !phoneNumber.isEmpty {
                                    submit()
                                }
                            }
                    }
                }
            }
        }
    

  2. There is a modifier that defines keyboard dismissal available since iOS 16:

    func scrollDismissesKeyboard(_ mode: ScrollDismissesKeyboardMode) -> some View
    

    You probably want the immediately mode.

    var body: some View{
        List {
            // etc.  
        }
        .scrollDismissesKeyboard(.immediately)
    }
    

    This does not dismiss the keyboard on tap but on scroll which is the typical iOS behaviour.

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