3

I need a custom "label" with the behavior of opening the date picker in some kind of popover, even on the iPhone.

When I use the built in DatePicker with compact format, I have the behavior with opening the wheels in a popover, but I cannot customize the look of the "collapsed" version with the gray background (in fact, I can change it to some other color, but not to white e.g., it simply doesn't work).

Another option would be to have a custom Text wrapped inside a Button and then open the DatePicker, but I don't know how to achieve the popover effect on the iPhone. So I guess the first option would be the easier one, but how can I achieve a custom layout for the compact date picker? Nothing super fancy, just something like this:

enter image description here

instead of something like this

enter image description here

swalkner
  • 16,679
  • 31
  • 123
  • 210

1 Answers1

4

its more of a proof of concept, but this might be a way:


import SwiftUI

struct ContentView: View {
    @State private var showPicker = true
    @State var selectedDate = Date()

        Button {
            withAnimation {
                showPicker.toggle()
            }
        }  label: {
            Text(Text(selectedDate.getFormattedDate(format:"HH:mm:")))
                .padding()
                .padding(.horizontal)
                .background(
                    RoundedRectangle(cornerRadius: 10)
                        .stroke(Color.gray)
                )
        }
        .background(
            DatePicker("", selection: $selectedDate, displayedComponents: .hourAndMinute)
                .datePickerStyle(.wheel)
                .frame(width: 200, height: 100)
                .clipped()
                .background(Color.gray.cornerRadius(10))
                .opacity(showPicker ? 1 : 0 )
                .offset(x: 50, y: 90)
               ).onChange(of: selectedDate) { newValue in
                   
                   withAnimation {
                       showPicker.toggle()
                   }
               }
}

Note that DidSet or willSet is not possible for Objects, however, we had a nice workaround onChange. When date changed, just toggle, done.

kelalaka
  • 5,064
  • 5
  • 27
  • 44
ChrisR
  • 9,523
  • 1
  • 8
  • 26
  • this is already a huge step forward, thanks for that! I have to play with `zindex` a little bit, but there seems to be a working solution for that. The only thin that's not super nice yet is that the user has to tap the Button again to hide the `DatePicker`; do you see any possibility to let them tap anywhere to hide it? – swalkner Feb 25 '22 at 20:46
  • Unfortunately canceling on tap anywhere is a quite complicated matter in SwiftUI ... you can put an "almost" transparent view (opacity 0.01) behind everything and detect a tap on that. – ChrisR Feb 25 '22 at 21:00
  • the other way would be wrapping a UIKit UIDatePicker into an UIViewRepresentable and changing its label. But I'm not a UIKit guy :) – ChrisR Feb 25 '22 at 21:03
  • You can add a done button by overlay to dismiss the picker. I did. – Tanvirgeek Jun 24 '22 at 04:00
  • @swalkner did you solved to hide when date selected? – kelalaka Oct 12 '22 at 18:52
  • @swalkner Ok, I've found a nice workaround see the updated answer. – kelalaka Oct 12 '22 at 19:51