I'm trying to develop a custom control for use in a form that behaves in a similar manner to SwiftUI's DatePicker (within a Form it defaults to GraphicalDatePickerStyle).
Apple's control displays the calendar and time picker modally with the background blurred out. I can manage the modal presentation using the .fullScreenCover modifier. Background blur is also possible by adding a UIVisualEffectView to the background of the displayed control. However, the blur applied in this way is far too heavy-handed even using the lightest options provided by the system defaults. I'm also unhappy about the reliance on modifying superview backgrounds via DispatchQueue.main.async - it works but makes me feel uncomfortable.
Is there any way of getting closer to Apple's implementation? My attempts to add a vibrancy effect layer didn't get me anywhere and you're not supposed to touch the alpha of UIEffectViews according to documentation...
Code and comparison of the visual effects (desired and current iteration) below:
import SwiftUI
struct ContentView: View {
@State private var isPresented = false
@State private var interval: TimeInterval = 0
var body: some View {
Form {
Text("Row")
Text("Row")
Text("Row")
Text("Row")
DatePicker("Date", selection: .constant(Date()))
Button("Present custom control") {
self.isPresented.toggle()
}
.fullScreenCover(isPresented: $isPresented) {
ZStack {
Color.white.opacity(0.1)
.edgesIgnoringSafeArea(.all)
// below is a placeholder for the custom control
Button("Dismiss") { isPresented.toggle() }
.frame(width: 200, height: 200)
.background(Color.white)
.cornerRadius(16)
}
.background(BackgroundBlurView())
}
Text("Other stuff here")
.background(Color.red)
}
}
}
struct BackgroundBlurView: UIViewRepresentable {
func makeUIView(context: Context) -> UIView {
let view = UIVisualEffectView(effect: UIBlurEffect(style: .systemUltraThinMaterial))
// this works but it looks a bit hacky... code smell?
DispatchQueue.main.async {
view.superview?.superview?.backgroundColor = .clear
}
return view
}
func updateUIView(_ uiView: UIView, context: Context) {
// nothing needed here
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
Group {
ContentView()
}
}
}


