swiftuidatepicker

Is it possible to dismiss the DatePicker's calendar when you tap a date?


I have a basic SwiftUI date picker that shows a calendar widget when tapped:

DatePicker(
  "Date",
  selection: $date,
  in: ...Date(),
  displayedComponents: [.date]
)

expanded calendar

When you select a date (8th October in the example above), the calendar remains on screen and in order to collapse it, you need to tap outside of it.

Is it possible to automatically collapse it when a date is selected?


Solution

  • I ended up with a rather hacky solution that seems to be doing the job.

    Add a @State variable that holds the calendar ID:

    @State private var calendarId: Int = 0
    

    Chain the DatePicker call with .id, .onChange and .onTapGesture actions:

    DatePicker(
      "Date", selection: $date, in: ...Date(), displayedComponents: [.date]
    )
    .id(calendarId)
    .onChange(of: date) { _ in
      calendarId += 1
    })
    

    Please note, this solution has a bug that will result in the calendar being dismissed when you change the month or year. See tier777's answer below for an iOS 17 solution.

    Xcode 15 update (November 2023)

    In Xcode versions < 15 you might also need an .onTapGesture action on the above:

    .onTapGesture {
      calendarId += 1
    }
    

    But in Xcode 15 this seems to be causing the following crash:

    This UITargetedPreview initializer requires that the view is in a window, but it is not. Either fix that, or use the other initializer that takes a target.