我有一个应用程序,让用户选择
colorScheme
,这样它就可以保持自适应模式,或者可以强制进入白天或夜间模式,即使设备的系统方案不同。
问题是
ColorPicker
呈现的弹出窗口并不反映所选的 ColorScheme
,而仅反映(设备的)系统之一。
建议的代码会生成一个列表,例如自动反映
preferredColorScheme
。然后它会生成一个 ColorPicker
来设置背景颜色和一些可点击的文本,以将 colorScheme
更改为 setColorScheme
。
import SwiftUI
struct ColorPickerTest: View {
@Environment(\.colorScheme) var colorScheme
@State var setColorScheme: ColorScheme? = nil
@State var selectedColor = Color.green
var body: some View {
ZStack {
selectedColor.ignoresSafeArea()
VStack {
List {
ForEach(1..<6) { n in
Text("item \(n)")
}
}
.frame(height: 500)
.cornerRadius(30)
ColorPicker("Color", selection: $selectedColor)
.fixedSize().padding()
.background(colorScheme == .dark ? .blue : selectedColor)
.cornerRadius(30).padding()
HStack {
Text("Theme:")
Text("Adaptive").onTapGesture { setColorScheme = nil }
Text("Night").onTapGesture { setColorScheme = .dark }
Text("Day").onTapGesture { setColorScheme = .light }
}
}
}
.preferredColorScheme(setColorScheme)
}
}
#Preview {
ColorPickerTest()
}
这个效果很好,除了
ColorPicker
呈现的弹出窗口,在这种情况下,setColorScheme
没有任何效果,仅反映系统方案,忽略强加的preferredColorScheme
。
有人有解决办法或解释吗?
我不知道如何让 SwiftUI 的
ColorPicker
自动应用背景颜色,但我可以提出这个小技巧:
ColorPicker
的窗口是我们可以在应用程序的窗口层次结构中搜索的NSColorPanel
。在那里我们可以设置它的属性。
struct ContentView: View {
@State private var selectedColor: Color = .gray
var body: some View {
VStack {
ColorPicker("Pick", selection: $selectedColor)
.onAppear {
DispatchQueue.main.async {
guard let panel = colorPanel else { return }
/// Now we can access all NSWindow/NSPanel/NSColorPanel properties
print("\(panel.backgroundColor)") // "Optional(Catalog color: System windowBackgroundColor)"
panel.backgroundColor = NSColor(selectedColor)
// panel.titlebarAppearsTransparent = true
// panel.titleVisibility = NSWindow.TitleVisibility.hidden
// panel.title = "Random text"
print("\(panel.backgroundColor)")
}
}
.onChange(of: selectedColor) { newColor in
colorPanel?.backgroundColor = NSColor(selectedColor)
}
}
.padding()
.fixedSize()
.background(selectedColor)
}
}
请注意,在
onAppear
中,我们需要使用 DispatchQueue.main.async
“等待”面板才能存在于应用程序的 windows
数组中。
您仍然需要了解如何应用自适应配色方案,但如果需要,如何应用颜色。