I'm currently looking into Dark Mode in my App. While Dark Mode itself isn't much of a struggle because of my SwiftUI basis i'm struggling with the option to set the ColorScheme independent of the system ColorScheme.
I found this in apples human interface guidelines and i'd like to implement this feature. (Link: Human Interface Guidelines)
Any idea how to do this in SwiftUI? I found some hints towards @Environment
but no further information on this topic. (Link: Last paragraph)
To change the color scheme of a single view (Could be the main ContentView
of the app), you can use the following modifier:
.preferredColorScheme(.dark) // or `.light or` `nil` to use the current scheme
or
.environment(\.colorScheme, .light) // or `.dark`
You can apply it to the ContentView
inside the root WindowGroup
to make your entire app dark!
Assuming you didn't change the ContentView
name in scene delegate or @main
UIKit
parts and The SwiftUI
)First you need to access the window to change the app colorScheme that called UserInterfaceStyle
in UIKit
.
I used this in SceneDelegate
(How to add scene delegate in SwiftUI):
private(set) static var shared: SceneDelegate?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
Self.shared = self
...
}
Then you need to bind an action to the toggle. So you need a model for it.
struct ToggleModel {
var isDark: Bool = true {
didSet {
SceneDelegate.shared?.window!.overrideUserInterfaceStyle = isDark ? .dark : .light
}
}
}
At last, you just need to toggle the switch:
struct ContentView: View {
@State var model = ToggleModel()
var body: some View {
Toggle(isOn: $model.isDark) {
Text("is Dark")
}
}
}
Each UIView
has access to the window, So you can use it to set the . overrideUserInterfaceStyle
value to any scheme you need.
myView.window?.overrideUserInterfaceStyle = .dark // or `.light` or `.unspecified` to use the current scheme