2021年1月19日星期二

SwiftUI: How to let the user set the app appearance in real-time w/ options "light", "dark", and "system"?

I am currently trying to implement a solution in an app where the user is supposed to be able to switch the app's appearance in real-time with the following options:

  • System (applying whatever appearance is set in the iOS settings for the device)
  • Light (applying .light color scheme)
  • Dark (applying . dark color scheme)

Setting light and dark color schemes has proven to be quite easy and responsive using .preferredColorScheme(); however, I have not yet found any satisfying solution for the "System" option.

My current approach is the following:

  1. Getting the device color scheme using @Environment(.colorScheme) in ContentView
  2. Creating a custom view modifier for applying the respective color scheme on whatever view
  3. Using a modifier on "MainView" (that's where the real content of the app is supposed to live) to switch between the color schemes

My idea was to embed MainView in ContentView so that the @Environment(.colorScheme) would not be disturbed by any colorScheme that is applied to MainView.

However, it still doesn't work as supposed: When setting light and dark appearance, everything works as intended. However, when switching from light/dark to "system", the change in appearance is only visible after re-launching the app. Expected behavior, however, would be that the appearance changes instantly.

Any ideas on this?

Here are the relevant code snippets:

Main view

import SwiftUI    struct MainView: View {        @EnvironmentObject var settings: UserSettings      @AppStorage("selectedAppearance") var selectedAppearance = 0        var body: some View {          VStack {              Spacer()              Button(action: {                  selectedAppearance = 1              }) {                  Text("Light")              }              Spacer()              Button(action: {                  selectedAppearance = 2              }) {                  Text("Dark")              }              Spacer()              Button(action: {                  selectedAppearance = 0              }) {                  Text("System")              }              Spacer()          }      }  }  

ContentView

import SwiftUI    struct ContentView: View {        @Environment(\.colorScheme) var colorScheme      @EnvironmentObject var settings: UserSettings        var body: some View {          MainView()              .modifier(ColorSchemeModifier(colorScheme: colorScheme))              .environmentObject(settings)      }  }  

"Utilities"

import Foundation  import SwiftUI    class UserSettings: ObservableObject {      @Published var colorSchemeShow: ColorScheme = .light  }    struct ColorSchemeModifier: ViewModifier {        @AppStorage("selectedAppearance") var selectedAppearance: Int = 0      var colorScheme: ColorScheme        func body(content: Content) -> some View {          if selectedAppearance == 2 {              return content.preferredColorScheme(.dark)          } else if selectedAppearance == 1 {              return content.preferredColorScheme(.light)          } else {              return content.preferredColorScheme(colorScheme)          }      }  }  
https://stackoverflow.com/questions/65798263/swiftui-how-to-let-the-user-set-the-app-appearance-in-real-time-w-options-lig January 20, 2021 at 03:31AM

没有评论:

发表评论