I'm having a strange issue where the edges of my background view are flickering white when the sheet is presented/dismissed. The issue only seems to be visible when the system is in Light Mode, Dark Mode is fine.
You can see it here - flickering video demo
Has anyone seen this and know how to fix it?
import SwiftUI
struct ContentView: View {
@State private var isShowing: Bool = false
var body: some View {
ZStack {
Color.black
.ignoresSafeArea()
Button {
isShowing = true
} label: {
Label("show", systemImage: "questionmark.circle")
}
}
.sheet(isPresented: $isShowing) {
EmptyView()
}
}
}
By inspecting the view hierarchy, we can see that SwiftUI presents your root view using a UIHostingController
. The view
of this hosting controller has its backgroundColor
set to UIColor.systemBackground
. Your Color.black
is then overlayed on top of that.
As you know, when a large sheet is presented, the view behind the sheet is designed to shrink and shift downwards a little bit. When you drag the sheet around, the view behind the sheet also moves around a bit. What is happening here seems to be the movement of Color.black
isn't quite in sync with the UIView
that is hosting it. Therefore, sometimes some of that .systemBackground
color under the Color.black
is revealed. .systemBackground
is a white color in light mode, so you can clearly see it. It is a black color in dark mode, so it blends in with Color.black
and you don't notice it.
I don't think you can fix the movements being out of sync. You'll have to wait for Apple to do it. What you can do is set the background color to UIColor.black
so it is not noticeable even in light mode.
struct BackgroundFixer: UIViewControllerRepresentable {
class VC: UIViewController {
override func willMove(toParent parent: UIViewController?) {
// "parent" will be the UIHostingController we want when this
// is added as a background to the root ZStack
parent?.view.backgroundColor = .black
}
}
func makeUIViewController(context: Context) -> VC {
VC()
}
func updateUIViewController(_ uiViewController: VC, context: Context) {
}
}
// Add this to the ZStack
ZStack {
Color.black
.ignoresSafeArea()
Button {
isShowing = true
} label: {
Label("show", systemImage: "questionmark.circle")
}
}
.background {
BackgroundFixer()
}
.sheet(isPresented: $isShowing) {
EmptyView()
}