Mal*_*ito 1 color-scheme ios swift swiftui ios-darkmode
我目前正在尝试在应用程序中实现一个解决方案,用户应该能够使用以下选项实时切换应用程序的外观:
事实证明,使用 .preferredColorScheme() 设置浅色和深色配色方案非常容易且响应迅速;但是,对于“系统”选项,我还没有找到任何令人满意的解决方案。
我目前的方法如下:
我的想法是在 ContentView 中嵌入 MainView,这样@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()
}
}
}
Run Code Online (Sandbox Code Playgroud)
内容视图
import SwiftUI
struct ContentView: View {
@Environment(\.colorScheme) var colorScheme
var body: some View {
MainView()
.modifier(ColorSchemeModifier(colorScheme: colorScheme))
}
}
Run Code Online (Sandbox Code Playgroud)
“实用程序”
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)
}
}
}
Run Code Online (Sandbox Code Playgroud)
它适用于
\n.preferredColorScheme(selectedAppearance == 1 ? .light : selectedAppearance == 2 ? .dark : nil)\nRun Code Online (Sandbox Code Playgroud)\niOS 14.5+: \n就是这样。他们让“nil”起作用来重置您的首选颜色方案。
\niOS14:
\n唯一的问题是您必须重新加载应用程序才能使系统正常工作。我可以想到一个解决方法 - 当用户选择 \xe2\x80\x9csystem\xe2\x80\x9d 时,您首先确定当前的 colorScheme 是什么,将其更改为它,然后才将 selectedAppearance 更改为 0。
\n编辑:
\n这是工作思路:
\nstruct MainView: View {\n @Binding var colorScheme: ColorScheme\n @AppStorage("selectedAppearance") var selectedAppearance = 0\n\n var body: some View {\n VStack {\n Spacer()\n Button(action: {\n selectedAppearance = 1\n }) {\n Text("Light")\n }\n Spacer()\n Button(action: {\n selectedAppearance = 2\n }) {\n Text("Dark")\n }\n Spacer()\n Button(action: {\n if colorScheme == .light {\n selectedAppearance = 1\n }\n else {\n selectedAppearance = 2\n }\n DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(2)) {\n selectedAppearance = 0\n }\n }) {\n Text("System")\n }\n Spacer()\n }\n }\n}\n\nstruct ContentView: View {\n @AppStorage("selectedAppearance") var selectedAppearance = 0\n @Environment(\\.colorScheme) var colorScheme\n @State var onAppearColorScheme: ColorScheme = .light //only for iOS<14.5\n\n var body: some View {\n MainView(colorScheme: $onAppearColorScheme)\n .onAppear { onAppearColorScheme = colorScheme } //only for iOS<14.5\n .preferredColorScheme(selectedAppearance == 1 ? .light : selectedAppearance == 2 ? .dark : nil) }\n}\nRun Code Online (Sandbox Code Playgroud)\n有一个小问题 -> 它只能作为 onAppear 而不是 onChange (不知道为什么)
\n我最终使用了以下解决方案,这是对@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()
})
}
}
Run Code Online (Sandbox Code Playgroud)
帮手类
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
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
715 次 |
| 最近记录: |