Hiding the keyboard when scrolling in SwiftUI

Apr 21, 2024#swiftui

In SwiftUI, it’s common to hide the keyboard when scrolling to improve user experience, especially if the keyboard is obscuring content on the screen.

For most cases, using the scrollDismissesKeyboard modifier is the simpler and more recommended approach, especially with iOS 16 and later. It provides a declarative way to handle keyboard dismissal and offers different behavior options.

The custom gesture recognizer method might be useful for situations where you need more granular control over the dismissal behavior or are working with older SwiftUI versions.

Using scrollDismissesKeyboard modifier

This is the recommended approach introduced in iOS 16. It offers fine-grained control over how the keyboard dismissal behaves when scrolling. Here’s how to use it:

import SwiftUI

struct ContentView: View {
    @State private var firstName = ""
    @State private var lastName = ""
    @State private var email = ""

    var body: some View {
        Form {
            Section(header: Text("Personal Information")) {
                TextField("First Name", text: $firstName)
                TextField("Last Name", text: $lastName)
                TextField("Email", text: $email)
            }
        }
        .scrollDismissesKeyboard(.interactively)
    }
}

You can provide an argument to the scrollDismissesKeyboard modifier to specify how the keyboard should dismiss:

  • .automatic (default): SwiftUI decides the best behavior based on the context.
  • .immediately: Hides the keyboard as soon as any scrolling starts.
  • .interactively: Hides the keyboard as the user scrolls further, similar to dragging it down.
  • .never: Scrolling won’t dismiss the keyboard at all.

Using a custom gesture recognizer

While the scrollDismissesKeyboard modifier is generally preferred, this approach can be useful for more specific scenarios in older iOS versions.

This method involves creating a gesture recognizer that detects dragging on your scrollable content and then resigning the first responder (which hides the keyboard)

import SwiftUI

struct ContentView: View {
    @State private var text: String = ""
    
    var body: some View {
        ScrollView {
            TextField("Enter Text", text: $text)
        }
        .gesture(
            DragGesture()
                .onChanged { _ in
                    UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
                }
        )
    }
}

DragGesture is a gesture recognizer that detects dragging motions performed by the user. It’s commonly used for implementing interactive drag-and-drop behavior or for capturing drag gestures to initiate actions in your app.

This gesture provides information about the drag, such as the translation (distance moved), the location of the drag, and whether the drag is currently in progress or has ended.