我想在工作表中有一个系统/浅色/深色模式选择器以及其他设置。
选择不同的方案确实会正确更改 ContentView 中的 UI(工作表后面),但工作表本身保留旧方案,必须关闭并再次打开。
我究竟做错了什么?
例子:
import SwiftUI
struct ContentView: View {
@EnvironmentObject var viewManager: ViewManager
@State var showSettingsSheet = false
var body: some View {
NavigationView {
List {
Text("Some content 1")
Text("Some content 2")
}
.toolbar {
ToolbarItem {
Button(action: {
showSettingsSheet.toggle()
}){
Image(systemName: "gearshape.fill")
}
.sheet(isPresented: $showSettingsSheet){SettingsSheet()}
}
}
}
.preferredColorScheme(viewManager.colorScheme == "Light" ? .light : viewManager.colorScheme == "Dark" ? .dark : nil)
}
}
Run Code Online (Sandbox Code Playgroud)
struct SettingsSheet: View {
@Environment (\.presentationMode) var presentationMode
@EnvironmentObject var viewManager: ViewManager
var body: some View {
NavigationView{
GroupBox {
Picker("Display Mode", selection: $viewManager.colorScheme) {
Text("System").tag("System")
Text("Light").tag("Light")
Text("Dark").tag("Dark")
}
.pickerStyle(.segmented)
}
.toolbar {
ToolbarItem {
Button(action: {
presentationMode.wrappedValue.dismiss()
}){
Text("Done")
}
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
class ViewManager: ObservableObject {
@AppStorage("colorScheme") var colorScheme: String = "System"
}
Run Code Online (Sandbox Code Playgroud)
通过巨大的解决方法,我确实成功地完成了这项工作。不过,向苹果报告这一情况可能是值得的。
在工作表中获取 colorScheme 更新时出现问题,但我们可以将此 colorScheme 环境变量附加到另一个已发布的变量,然后在工作表中使用该变量。
struct ContentView: View {
@Environment(\.colorScheme) private var colorScheme
@EnvironmentObject var settings: Settings
var body: some View {
ContentView()
.preferredColorScheme(!settings.automaticAppearance ? (settings.lightAppearance ? .light : .dark) : nil)
.environmentObject(settings)
.onChange(of: colorScheme) { newColorScheme in
// update color scheme to settings (from system environment variable)
settings.systemColorScheme = newColorScheme
}
}
}
Run Code Online (Sandbox Code Playgroud)
final class Settings: ObservableObject {
@Environment(\.colorScheme) var colorScheme
@Published var lightAppearance: Bool {
didSet {
UserDefaults.standard.set(lightAppearance, forKey: "light_appearance")
}
}
@Published var automaticAppearance: Bool {
didSet {
UserDefaults.standard.set(automaticAppearance, forKey: "automatic_appearance")
}
}
@Published var systemColorScheme: ColorScheme {
didSet {
UserDefaults.standard.set(systemColorScheme.hashValue, forKey: "system_color_scheme")
}
}
init() {
self.lightAppearance = UserDefaults.standard.object(forKey: "light_appearance") as? Bool ?? true
self.automaticAppearance = UserDefaults.standard.object(forKey: "automatic_appearance") as? Bool ?? true
self.systemColorScheme = UserDefaults.standard.object(forKey: "system_color_scheme") as? ColorScheme ?? .light
}
}
Run Code Online (Sandbox Code Playgroud)
我希望用户能够切换灯光模式,并选择使用系统配色方案的“自动”选项。在我的设置表中:
struct SettingsView: View {
@Environment(\.colorScheme) var colorScheme
@EnvironmentObject var settings: Settings
var body: some View {
List {
Section(header: Text(NSLocalizedString("appearance", comment: "Appearance"))) {
Group {
// appearance
Toggle("Light mode", isOn: $settings.lightAppearance)
.onChange(of: settings.lightAppearance) { lightAppearance in
// if light/dark appearance was set, disable automatic appearance
settings.automaticAppearance = false
}
Toggle(isOn: $settings.automaticAppearance) {
Text(NSLocalizedString("automatic", comment: "Automatic"))
}
}
}
}
.preferredColorScheme(settings.automaticAppearance ? settings.systemColorScheme : (settings.lightAppearance ? .light : .dark))
}
}
Run Code Online (Sandbox Code Playgroud)
简而言之:使用不同的已发布变量在工作表中侦听,因为环境的配色方案存在问题。
您必须colorScheme手动提供工作表,因为它位于视图层次结构之外,即:
struct ContentView: View {
@EnvironmentObject var viewManager: ViewManager
@State var showSettingsSheet = false
var body: some View {
NavigationView {
List {
Text("Some content 1")
Text("Some content 2")
}
.toolbar {
ToolbarItem {
Button(action: {
showSettingsSheet.toggle()
}){
Image(systemName: "gearshape.fill")
}
.sheet(isPresented: $showSettingsSheet){
SettingsSheet()
.preferredColorScheme(viewManager.colorScheme == "Light" ? .light : viewManager.colorScheme == "Dark" ? .dark : nil) // HERE
}
}
}
}
.preferredColorScheme(viewManager.colorScheme == "Light" ? .light : viewManager.colorScheme == "Dark" ? .dark : nil)
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1218 次 |
| 最近记录: |