SwiftUI — preferredColorScheme

preferredColorScheme 是什么? #

preferredColorSchemeSwiftUI 的一个视图修饰符,用来指定某个视图的外观样式(Light 模式或 Dark 模式)。通过它,可以为某些视图强制应用特定的颜色模式(比如浅色模式或深色模式),而不跟随系统的全局设置。

该修饰符通常用于以下场景:

  • 在某些视图中使用特殊的颜色模式(例如,某些页面始终保持深色主题)。
  • 模拟不同的外观模式进行调试。
  • 为用户定制的应用主题和系统主题之间提供独立控制。

基本用法 #

1. 强制视图为深色或浅色模式 #

import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            Text("Preferred Color Scheme Example")
                .font(.title)
                .padding()
        }
        .preferredColorScheme(.dark) // 强制此视图为深色模式显示
    }
}

解释

  • .preferredColorScheme(.dark):强制整个视图始终显示为深色模式。
  • .preferredColorScheme(.light):将视图限定为浅色模式。

2. 动态切换颜色模式 #

使用 @AppStorage 或其他状态变量,动态更改视图的颜色模式。

import SwiftUI

struct ContentView: View {
    @AppStorage("isDarkMode") private var isDarkMode = false // 保存用户偏好
    
    var body: some View {
        VStack {
            Text("Current Mode: \(isDarkMode ? "Dark" : "Light")")
                .padding()
            
            Button(action: {
                isDarkMode.toggle() // 切换颜色模式偏好
            }) {
                Text("Switch Mode")
            }
        }
        .preferredColorScheme(isDarkMode ? .dark : .light) // 根据用户设置切换模式
    }
}

解释

  • 借助 @AppStorage,将用户的颜色偏好保存到 UserDefaults 中(例如,isDarkMode)。
  • 当用户点击按钮后,颜色模式在浅色和深色之间切换。

使用场景 #

1. 针对特定视图强制主题 #

某些页面可能需要特定的配色方案来适应内容设计,例如:

  • 阅读器应用中的阅读模式页面始终为深色。
  • 音乐或视频播放页面保持深色(减少干扰)。
  • 应用主界面随系统主题变更,但某些子页面有独立的主题样式。
示例:用户设置页面始终为浅色模式 #
struct SettingsView: View {
    var body: some View {
        VStack {
            Text("Settings")
                .font(.largeTitle)
        }
        .preferredColorScheme(.light) // 强制页面为浅色模式
    }
}

2. 调试外观模式 #

在开发应用时,你可以临时指定某个视图的外观模式,检查界面在不同模式下的显示效果。

struct DebugView: View {
    var body: some View {
        VStack {
            Text("Debugging Dark Mode")
        }
        .preferredColorScheme(.dark) // 在开发中用于模拟深色模式
    }
}

通过这种方式,你可以无需切换设备的系统主题,就能观察界面在深色和浅色模式下的表现。

3. 用户控制主题设置 #

允许用户选择应用主题(深色、浅色、系统)。利用 @AppStorageState 变量保存用户选择的偏好,并动态切换。

示例:用户选择的主题 #
struct ContentView: View {
    @AppStorage("theme") private var theme: String = "system" // 保存主题偏好
    
    var selectedScheme: ColorScheme? {
        // 返回对应的颜色模式
        switch theme {
        case "light": return .light
        case "dark": return .dark
        default: return nil // 跟随系统设置
        }
    }
    
    var body: some View {
        VStack {
            Picker("Theme", selection: $theme) {
                Text("System").tag("system")
                Text("Light").tag("light")
                Text("Dark").tag("dark")
            }
            .pickerStyle(SegmentedPickerStyle())
            .padding()
        }
        .preferredColorScheme(selectedScheme) // 应用用户选择的颜色模式
    }
}

解释

  • 通过 Picker 让用户选择应用主题。
  • 当用户更改主题时,根据选择更新 preferredColorScheme

4. 和 Accessibility 配合 #

某些场景下,特定颜色模式可能不适合所有用户,preferredColorScheme 可以让你为不同访问需求提供额外的范围支持。例如,为视力敏感的用户强制使用高对比度的深色界面。


注意事项 #

  1. preferredColorScheme 的作用范围仅限于视图本身及其子视图: 也就是说,如果视图 A 使用 .preferredColorScheme() 修改了颜色模式,只有它和它的子视图会受影响,其他视图不会被影响。

    例子

    VStack {
        ChildView()
        AnotherChildView()
    }
    .preferredColorScheme(.dark)
    

    在这个例子中,ChildViewAnotherChildView 都会应用深色模式。而父级视图或其他部分不会受影响。

  2. 不要滥用 preferredColorScheme: 如果应用中每个视图都使用它来显式设置主题,就会打破系统级的主题一致性,让用户体验变得混乱。应优先通过随系统调整的方式实现。

  3. 与系统偏好的兼容性: 如果希望默认跟随系统,同时允许用户自定义偏好,应该为 preferredColorScheme 设置一个动态状态(如 @AppStorage 状态变量)来切换。

  4. 多窗口中的一致性: 如果你的应用支持多窗口(如 iPad 多窗口模式),确保对主题的定义是合理的。对于整个应用最好能统一设置主题,尽量避免每个窗口有不同的颜色模式,除非有明确的设计需求。

  5. 调试时记得移除preferredColorScheme 是调试深色/浅色主题的好工具,但在上线前应确保不影响你应用的实际设计环境。


总结:什么时候使用 preferredColorScheme #

适合使用 preferredColorScheme 的场景: #

  1. 强制特定视图(如设计需要)总是使用浅色模式或深色模式。
  2. 应用中允许用户自定义主题时,动态设置识图颜色模式。
  3. 调试视图在不同颜色模式下的适配问题。
  4. 满足特定用户访问需求(如高对比模式)。

不适合使用的场景: #

  • 滥用该修饰符破坏系统级颜色规范(如全局每个页面独立配置)会导致用户困惑。
  • 希望统一跟随系统默认主题时,应该避免手动设置。

总结代码结构: #

  • 基础用法: 强制视图使用固定主题。

    .preferredColorScheme(.light) // 浅色
    .preferredColorScheme(.dark) // 深色
    .preferredColorScheme(nil) // 跟随系统默认
    
  • 动态用法: 根据状态切换不同模式。

    .preferredColorScheme(isDarkMode ? .dark : .light)
    
本文共 1704 字,上次修改于 Jan 8, 2025