SwiftUI Color Scheme
In UIKit app, If you would like to change the color scheme within the app. Setting UserInterfaceStyle
object to your root window would help.
Take a look at NetNewsWire iOS app. It gives Appearance settings where you can choose your color palette for the app. These are the possible options
- Automatic: respects system color scheme and changes whenever user switching between light and dark mode from the OS
- Light: Light mode for the whole app and didn’t respect the system color scheme
- Dark: dark mode for the whole app and didn’t respect the system color scheme
func updateUserInterfaceStyle() {
switch AppDefaults.userInterfaceColorPalette {
case .automatic:
window!.overrideUserInterfaceStyle = .unspecified
case .light:
window!.overrideUserInterfaceStyle = .light
case .dark:
window!.overrideUserInterfaceStyle = .dark
}
}
Setting unspecified
makes the app respects the system-wide color scheme here.
SwiftUI Way
SwiftUI gives us an environment variable and preferred color scheme modifier to change the color scheme.
struct ContentView: View {
@State var preferredColorScheme: ColorScheme? = nil
var body: some View {
List {
Button(action: {
preferredColorScheme = .light
}) {
HStack {
Text("Light")
Spacer()
if preferredColorScheme == .light {
selectedImage
}
}
}
Button(action: {
preferredColorScheme = .dark
}) {
HStack {
Text("Dark")
Spacer()
if preferredColorScheme == .dark {
selectedImage
}
}
}
}
.listStyle(InsetGroupedListStyle())
.preferredColorScheme(preferredColorScheme)
.navigationBarTitle("ColorScheme Test")
}
var selectedImage: some View {
Image(systemName: "checkmark")
.foregroundColor(.blue)
}
}
In the above code, we are setting the preferredColorScheme
modifier to our content view and changing it via @State
object. It will give us one view with two options where you can change the color scheme.
It’s also possible with the environment value like below
@main
struct ColorSchemeTestApp: App {
var body: some Scene {
WindowGroup {
ContentView()
.environment(\.colorScheme, .dark)
}
}
}
We can also get to know the currently selected color scheme via environment object like below.
@Environment(\.colorScheme) var colorScheme
NOTE
As of beta 2, there is no way that I can find, to set the colorScheme
to unspecified
to get automatic behaviour. I have even filed a Feedback. In case if you find a way to achieve it, let me know at twitter
I did create a sample project to explain the behaviour and you can find it here at Github.
Links
- Color Scheme Apple documentation
- Preferred Color Scheme modifier Apple documenation
- NetNewsWire project on Github