Reputation: 276
I'm using a toggle and @AppStorage to change the preferredColorScheme in my app. Dark mode and light mode works fine on Views other than sheets and full screen modals.
struct MyApp: App {
@AppStorage("darkMode") var darkMode = false
init() {
FirebaseApp.configure()
}
var body: some Scene {
WindowGroup {
ContentView()
.preferredColorScheme(darkMode ? .dark : .light)
}
}
}
App Settings View:
struct AppSettingsView: View {
@ObservedObject var appSettingsVM: AppSettingsViewModel
var body: some View {
ScrollView {
Toggle("Dark Mode", isOn: $appSettingsVM.darkMode.animation())
.toggleStyle(SwitchToggleStyle(tint: .orange))
.padding()
}
}
}
App Settings View Model:
class AppSettingsViewModel: ObservableObject {
@AppStorage("darkMode") var darkMode: Bool = false
}
There are multiple sheets and full screen modals under the Content View hierarchy and none of them respond to the changes in Color Scheme.
Upvotes: 2
Views: 1570
Reputation: 1579
If you want to change the color scheme for full app, do not use preferredColorScheme(.dark)
use environment instead
NavigationView {
//your code
}.environment(\.colorScheme, .dark)
this will affect all the child views of the NavigationView
Upvotes: 2
Reputation: 276
I modified the solution from a YouTube video and this works.
import Foundation
import UIKit
class ThemeManager {
static let shared = ThemeManager()
private init () {}
func handleTheme(darkMode: Bool, system: Bool) {
guard !system else {
UIApplication.shared.windows.first?.overrideUserInterfaceStyle = .unspecified
return
}
UIApplication.shared.windows.first?.overrideUserInterfaceStyle = darkMode ? .dark : .light
}
}
import SwiftUI
import Firebase
@main
struct MyApp: App {
@AppStorage("darkMode") var darkMode: Bool = false
@AppStorage("system") var system: Bool = true
init() {
FirebaseApp.configure()
}
var body: some Scene {
WindowGroup {
MainView(mainVM: MainViewModel())
.onAppear {
ThemeManager.shared.handleTheme(darkMode: self.darkMode, system: self.system)
}
}
}
struct AppSettingsView: View {
@ObservedObject var appSettingsVM: AppSettingsViewModel
var body: some View {
VStack {
HStack {
Text("App Settings")
.font(.title2)
.padding()
Spacer()
}
.padding(.horizontal)
Divider()
ScrollView {
HStack {
Text("Theme")
Spacer()
Menu {
Button("System") {
appSettingsVM.handleTheme(darkMode: false, system: true)
}
Button("Light") {
appSettingsVM.handleTheme(darkMode: false, system: false)
}
Button("Dark") {
appSettingsVM.handleTheme(darkMode: true, system: false)
}
} label: {
Text(appSettingsVM.darkModeLabel)
.frame(width: 80)
.padding(5)
.background(Color.orange)
.foregroundColor(.white)
.clipShape(RoundedRectangle(cornerRadius: 12))
}
}
.padding()
}
}
import SwiftUI
class AppSettingsViewModel: ObservableObject {
@AppStorage("darkMode") var darkMode: Bool = false
@AppStorage("system") var system: Bool = true
@Published var darkModeLabel = "System"
func handleTheme(darkMode: Bool, system: Bool) {
self.darkMode = darkMode
self.system = system
if darkMode == false && system == true {
withAnimation {
self.darkModeLabel = "System"
}
} else if darkMode == false && system == false {
withAnimation {
self.darkModeLabel = "Light"
}
} else {
withAnimation {
self.darkModeLabel = "Dark"
}
}
ThemeManager.shared.handleTheme(darkMode: self.darkMode, system: self.system)
}
}
Video link: https://www.youtube.com/watch?v=j7a4jvHz4MM
Upvotes: 1