I'm trying to achieve the simplest possible use case, but I can't figure it out. I have a picture of calendar. All I want is to show DatePicker popup when tapping the picture. I tried to put it inside ZStack, but by doing it I can't hide default data textfields:
ZStack {
Image("icon-calendar")
.zIndex(1)
DatePicker("", selection: $date)
.zIndex(2)
}
How to make this simple layout natively without ridiculous workarounds?
I'm having this problem too. I couldn't sleep for a few days thinking about the solution. I have googled hundred times and finally, I found a way to achieve this. It's 1:50 AM in my timezone, I can sleep happily now. Credit goes to chase's answer here
Demo here: https://media.giphy.com/media/2ILs7PZbdriaTsxU0s/giphy.gif
The code that does the magic
struct ContentView: View {
@State var date = Date()
var body: some View {
ZStack {
DatePicker("label", selection: $date, displayedComponents: [.date])
.datePickerStyle(CompactDatePickerStyle())
.labelsHidden()
Image(systemName: "calendar")
.resizable()
.frame(width: 32, height: 32, alignment: .center)
.userInteractionDisabled()
}
}
}
struct NoHitTesting: ViewModifier {
func body(content: Content) -> some View {
SwiftUIWrapper { content }.allowsHitTesting(false)
}
}
extension View {
func userInteractionDisabled() -> some View {
self.modifier(NoHitTesting())
}
}
struct SwiftUIWrapper<T: View>: UIViewControllerRepresentable {
let content: () -> T
func makeUIViewController(context: Context) -> UIHostingController<T> {
UIHostingController(rootView: content())
}
func updateUIViewController(_ uiViewController: UIHostingController<T>, context: Context) {}
}
Tried using Hieu's solution in a navigation bar item but it was breaking. Modified it by directly using SwiftUIWrapper
and allowsHitTesting
on the component I want to display and it works like a charm.
Also works on List and Form
struct StealthDatePicker: View {
@State private var date = Date()
var body: some View {
ZStack {
DatePicker("", selection: $date, in: ...Date(), displayedComponents: .date)
.datePickerStyle(.compact)
.labelsHidden()
SwiftUIWrapper {
Image(systemName: "calendar")
.resizable()
.frame(width: 32, height: 32, alignment: .topLeading)
}.allowsHitTesting(false)
}
}
}
struct SwiftUIWrapper<T: View>: UIViewControllerRepresentable {
let content: () -> T
func makeUIViewController(context: Context) -> UIHostingController<T> {
UIHostingController(rootView: content())
}
func updateUIViewController(_ uiViewController: UIHostingController<T>, context: Context) {}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With