ios - SwiftUI:如何让用户通过选项“light”、“dark”和“system”实时设置应用程序外观?
问题描述
我目前正在尝试在应用程序中实施解决方案,用户应该能够使用以下选项实时切换应用程序的外观:
- 系统(应用在设备的 iOS 设置中设置的任何外观)
- 光(应用 .light 配色方案)
- 深色(应用 .dark 配色方案)
事实证明,使用 .preferredColorScheme() 设置浅色和深色配色方案非常简单且响应迅速;但是,我还没有为“系统”选项找到任何令人满意的解决方案。
我目前的方法如下:
- 在 ContentView 中使用 @Environment(.colorScheme) 获取设备配色方案
- 创建自定义视图修改器以在任何视图上应用相应的配色方案
- 在“MainView”(应用程序的真实内容应该存在的地方)上使用修饰符在配色方案之间切换
我的想法是将 MainView 嵌入 ContentView 中,这样@Environment(.colorScheme) 就不会被应用于 MainView 的任何 colorScheme 干扰。
但是,它仍然不能按预期工作:设置明暗外观时,一切都按预期工作。但是,当从亮/暗切换到“系统”时,外观的变化只有在重新启动应用程序后才能看到。然而,预期的行为将是外观立即改变。
对此有什么想法吗?
以下是相关的代码片段:
主视图
import SwiftUI
struct MainView: View {
@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()
}
}
}
内容视图
import SwiftUI
struct ContentView: View {
@Environment(\.colorScheme) var colorScheme
var body: some View {
MainView()
.modifier(ColorSchemeModifier(colorScheme: colorScheme))
}
}
“实用程序”
import Foundation
import SwiftUI
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)
}
}
}
解决方案
我最终使用了以下解决方案,这是对@pgb 给出的答案的轻微改编:
内容视图:
struct ContentView: View {
@AppStorage("selectedAppearance") var selectedAppearance = 0
var utilities = Utilities()
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()
}
.onChange(of: selectedAppearance, perform: { value in
utilities.overrideDisplayMode()
})
}
}
助手类
class Utilities {
@AppStorage("selectedAppearance") var selectedAppearance = 0
var userInterfaceStyle: ColorScheme? = .dark
func overrideDisplayMode() {
var userInterfaceStyle: UIUserInterfaceStyle
if selectedAppearance == 2 {
userInterfaceStyle = .dark
} else if selectedAppearance == 1 {
userInterfaceStyle = .light
} else {
userInterfaceStyle = .unspecified
}
UIApplication.shared.windows.first?.overrideUserInterfaceStyle = userInterfaceStyle
}
}
推荐阅读
- javascript - JS ajax事件通过输入改变
- angular - Aws 放大登录、注册和确认签名工作流程问题
- amazon-web-services - Kinesis Firehose 可以进行过滤吗?
- javascript - 如何将一组数组(字符串格式)推送到数组中?
- oracle - 流水线函数在编译时给出“PLS-00630”错误
- python - 将 2 .CSV 与未知数量的列和名称进行比较
- r - 在时间序列中创建平稳性的问题
- lda - 如何获得两个模型的主题连贯性分数,然后将其用于比较?
- mysql - 如果 MySQL 数据库中不存在另一个对象,如何创建 SQL 查询来保存对象?
- nuxt.js - 在根路由 NuxtJS 中使用 get param