如何使用系统值选项实现配色方案切换



我已经使用本线程中的指南在我的应用程序中实现了暗/亮模式切换。下面的示例代码:

public struct DarkModeViewModifier: ViewModifier {
@AppStorage("isDarkMode") var isDarkMode: Bool = true
public func body(content: Content) -> some View {
content
.environment(.colorScheme, isDarkMode ? .dark : .light)
.preferredColorScheme(isDarkMode ? .dark : .light) // tint on status bar
}
}

称之为

Picker("Color", selection: $isDarkMode) {
Text("Light").tag(false)
Text("Dark").tag(true)
}
.pickerStyle(SegmentedPickerStyle())

如何通过添加System段来实现这一点?我曾想过将Int设置为默认设置,但我不知道如何将其与@AppStorage属性包装器联系起来。

此外,在SwiftUI中,观看系统模式更改是如何生效的?

更新:在iOS 15中,windows似乎已被弃用。如何以最理智的方式更新iOS 15?我已经看到了isKeyWindow的一些其他解决方案,但不确定如何在这里应用它。

要实现这一点,您需要将用户的显示首选项从Bool存储到自定义枚举。然后,通过此自定义枚举,可以确定外观是深色还是浅色,并基于此应用显示首选项。

样本代码:

struct ContentView: View {
enum DisplayMode: Int {
case system = 0
case dark = 1
case light = 2
}
@AppStorage("displayMode") var displayMode: DisplayMode = .system
func overrideDisplayMode() {
var userInterfaceStyle: UIUserInterfaceStyle
switch displayMode {
case .dark: userInterfaceStyle = .dark
case .light: userInterfaceStyle = .light
case .system: userInterfaceStyle = UITraitCollection.current.userInterfaceStyle
}
UIApplication.shared.windows.first?.overrideUserInterfaceStyle = userInterfaceStyle
}

var body: some View {
VStack {
Picker("Color", selection: $displayMode) {
Text("System").tag(DisplayMode.system)
Text("Light").tag(DisplayMode.light)
Text("Dark").tag(DisplayMode.dark)
}
.pickerStyle(SegmentedPickerStyle())
.onReceive([self.displayMode].publisher.first()) { _ in
overrideDisplayMode()
}
}.onAppear(perform: overrideDisplayMode)
}
}

基本上,你正在做的是

  • 为每个显示模式分配一个整数值(以便将其存储在@AppStorage中(
  • 设置选择器以在系统、深色和浅色之间进行选择,并将值保存在UserDefaults中
  • 通过打开@AppStorage值来确定应用程序是否处于黑暗模式
  • 使用UIApplication.shared.windows.first?.overrideInterfaceStyle通过视图和子视图传递自定义暗模式配置

感谢@diogo的解决方案。我已经为ios 15将其调整为一个自定义视图,可以在设置页面中使用:

struct DisplayModeSetting: View {
enum DisplayMode: Int {
case system, dark, light

var colorScheme: ColorScheme? {
switch self {
case .system: return nil
case .dark: return ColorScheme.dark
case .light: return ColorScheme.light
}
}

func setAppDisplayMode() {
var userInterfaceStyle: UIUserInterfaceStyle
switch self {
case .system: userInterfaceStyle = UITraitCollection.current.userInterfaceStyle
case .dark: userInterfaceStyle = .dark
case .light: userInterfaceStyle = .light
}
let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene
scene?.keyWindow?.overrideUserInterfaceStyle = userInterfaceStyle
}
}

@AppStorage("displayMode") var displayMode = DisplayMode.system

var body: some View {
HStack {
Text("Display mode:")
Picker("Is Dark?", selection: $displayMode) {
Text("System").tag(DisplayMode.system)
Text("Dark").tag(DisplayMode.dark)
Text("Light").tag(DisplayMode.light)
}
.pickerStyle(SegmentedPickerStyle())
.onChange(of: displayMode) { newValue in
print(displayMode)
displayMode.setAppDisplayMode()
}
}
}
}

最新更新