I have a question, how can I ignore or follow the iPadOs's color scheme? I searched all over the web and couldn't find an answer that could help me.
I created a Picker to choose between the options "Ignore system scheme" or "Follow system scheme". If the user tabs on "Ignore system scheme" the app should have its own color scheme and shouldn't follow the device Color scheme (e.g. Device Color Scheme: Dark · App's Color scheme: Light).
I've created an AppStorage property to check and change the app's color scheme between dark and light. Should I call it too for the "Ignore system scheme" function?
Here my code:
import SwiftUI
struct SLDarkmodeSettingsView: View {
@Environment(\.colorScheme) var colorScheme
@AppStorage("isDarkMode") private var isDarkMode = false
@State private var darkmodePicker = 0
var body: some View {
NavigationStack {
List {
Section() {
HStack {
Toggle(isOn: $isDarkMode) {
Text("Enable Darkmode")
}
.alert(isPresented: $isDarkMode) {
Alert(title: Text("Warning"), message: Text("Do you really want to enable Darkmode (beta)? Some modules are not adapted to darkmode."), primaryButton: .default(Text("Cancel"), action: {
isDarkMode = false
}), secondaryButton: .destructive(Text("Enable").fontWeight(.semibold), action: {
// TODO: Call the darkmode func
isDarkMode = true
}))
}
}
HStack {
// TODO: Link toggle and picker, add darkmode support in v.1.2
Picker(selection: $darkmodePicker, label: Text("Display mode")) {
Text("Ignore system scheme").tag(0)
Text("Follow system scheme").tag(1)
}
}
} header: {
Text("Darkmode settings")
} footer: {
Text("Toggle the button to enable Darkmode. Note if your system is on a light scheme and you've selected Follow system scheme the darkmode setting will be ignored. Please select 'Ignore system scheme'.")
}
}
.navigationTitle("Darkmode (BETA)")
.navigationBarTitleDisplayMode(.inline)
}
}
}
#Preview {
SLDarkmodeSettingsView()
}
Would you mind taking a look at my approach and letting me know if it's correct? Am I right? Your help would be greatly appreciated! 🙂
This can be done by setting the following key value pair in your Info.plist
to "Disable" the system color scheme.
<key>UIUserInterfaceStyle</key>
<string>Light</string>
Once you have it set, such that the app ignores the theme set by the device, the next step is to setup a way to handle swapping that theme. You can use .environment(\.colorScheme, .light)
view modifer on your base most view, to set that value. For example
var customColorScheme: ColorScheme {
return .dark
}
@main
struct YourAppName: App {
var body: some Scene {
YourMainLaunchView()
.environment(\.colorScheme, customColorScheme)
}
}
this should have the effect of all child views, of YourMainLaunchView()
respecting the environment object. However you should be aware that this is a one-way binding. So simply changing it, without refreshing the view in some manner, will result in nothing changing until the view is recomputed. You'll likely want to observe that value changing and handle that case where it's changed, but not updated immediately as you'd expect. A simple solution to that would be to replace customColorScheme
with a @State
object or a @EnvironmentObject
which is then replaced in the .environment(...)
modifier. When you work to implement it, it'll become apparent.