我目前正在我的应用程序中进入暗模式。虽然由于我的SwiftUI基础,暗模式本身并没有太大的麻烦,但我仍在努力选择独立于系统ColorScheme来设置ColorScheme的选项。
I found this in apples human interface guidelines,我想实现此功能。 (链接:Human Interface Guidelines)
有人知道如何在SwiftUI中做到这一点吗?我发现了一些有关@Environment
的提示,但没有有关此主题的更多信息。 (链接:Last paragraph)
答案 0 :(得分:3)
使用@AppStorage
切换暗模式的演示
PS:对于全局切换,应将修饰符添加到WindowGroup / MainContentView
import SwiftUI
struct SystemColor: Hashable {
var text: String
var color: Color
}
let backgroundColors: [SystemColor] = [.init(text: "Red", color: .systemRed), .init(text: "Orange", color: .systemOrange), .init(text: "Yellow", color: .systemYellow), .init(text: "Green", color: .systemGreen), .init(text: "Teal", color: .systemTeal), .init(text: "Blue", color: .systemBlue), .init(text: "Indigo", color: .systemIndigo), .init(text: "Purple", color: .systemPurple), .init(text: "Pink", color: .systemPink), .init(text: "Gray", color: .systemGray), .init(text: "Gray2", color: .systemGray2), .init(text: "Gray3", color: .systemGray3), .init(text: "Gray4", color: .systemGray4), .init(text: "Gray5", color: .systemGray5), .init(text: "Gray6", color: .systemGray6)]
struct DarkModeColorView: View {
@AppStorage("isDarkMode") var isDarkMode: Bool = true
var body: some View {
Form {
Section(header: Text("Common Colors")) {
ForEach(backgroundColors, id: \.self) {
ColorRow(color: $0)
}
}
}
.toolbar {
ToolbarItem(placement: .principal) { // navigation bar
Picker("Color", selection: $isDarkMode) {
Text("Light").tag(false)
Text("Dark").tag(true)
}
.pickerStyle(SegmentedPickerStyle())
}
}
.modifier(DarkModeViewModifier())
}
}
private struct ColorRow: View {
let color: SystemColor
var body: some View {
HStack {
Text(color.text)
Spacer()
Rectangle()
.foregroundColor(color.color)
.frame(width: 30, height: 30)
}
}
}
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
}
}
struct DarkModeColorView_Previews: PreviewProvider {
static var previews: some View {
NavigationView {
DarkModeColorView()
}
}
}
答案 1 :(得分:3)
@Mojtaba Hosseini's 的回答确实帮助了我,但我使用的是 iOS14 的 @main
而不是 SceneDelegate
,以及一些 UIKit
视图,所以我最终使用了类似的东西这(这不会切换模式,但它会在 SwiftUI
和 UIKit
之间设置暗模式:
@main
struct MyTestApp: App {
@Environment(\.scenePhase) private var phase
var body: some Scene {
WindowGroup {
ContentView()
.accentColor(.red)
.preferredColorScheme(.dark)
}
.onChange(of: phase) { _ in
setupColorScheme()
}
}
private func setupColorScheme() {
// We do this via the window so we can access UIKit components too.
let window = UIApplication.shared.windows.first
window?.overrideUserInterfaceStyle = .dark
window?.tintColor = UIColor(Color.red)
}
}
答案 2 :(得分:0)
首先,您需要访问窗口以更改在UserInterfaceStyle
中调用UIKit
的应用colorScheme。
我在SceneDelegate
中使用了它:
private(set) static var shared: SceneDelegate?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
Self.shared = self
,,,
}
然后,您需要将操作绑定到切换。因此,您需要一个模型。
struct ToggleModel {
var isDark: Bool = true {
didSet { SceneDelegate.shared?.window!.overrideUserInterfaceStyle = isDark ? .dark : .light }
}
}
最后,您只需要切换开关即可
struct ContentView: View {
@State var model = ToggleModel()
var body: some View {
Toggle(isOn: $model.isDark) {
Text("is Dark")
}
}
}