mucahid-erdogan
mucahid-erdogan

Reputation: 276

SwiftUI Dark Mode not applying to sheets

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

Answers (2)

Nasib
Nasib

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

mucahid-erdogan
mucahid-erdogan

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

Related Questions