在深色或浅色模式下管理颜色的最佳方式

The best way to manage colours in dark or light mode

在工作中,我们有一个颜色设计系统,例如

红-1 红2 红 3

绿色-1 绿2 绿色-3

它们背后的十六进制代码可能会发生变化,但一个组件或一组组件也可能会发生变化,例如,将它们的颜色从 red-1 更改为 red-2。

我们还想处理深色模式。在浅色模式下,您的背景可能为 red-1,但在深色模式下,它需要为 green-1。这意味着我们可能还需要语义颜色,例如:

background-1(浅色模式为红色1,深色模式为绿色1) 前景 1

等等

我知道用最少的样板来处理黑暗模式的最简单方法是使用资产目录。因此,您将拥有一个名为 background-1 的颜色资产,并且具有深色和浅色模式颜色。

问题是,该颜色无法引用其他自定义颜色(如 red-1)。相反,您必须手动输入十六进制代码,这意味着如果 red-1 发生变化,您将非常头疼地更改所有使用 red-1 的语义颜色。

另一方面,据我所知,如果您走程序化路线(即为您的 red-1、green-1 使用资产目录,并为您的语义使用 class/enum颜色)你需要为每个使用这些颜色的 class 添加大量样板(我认为是 traitCollectionDidChange?)。

有谁能想到一个快乐的媒介吗?如果存在外部工具,很乐意使用。

编辑:我有一个想法:

  1. Colors.xcassets - 这有我们的语义颜色
  2. ColorSystem.json - 这有真实的颜色和它们的六边形(red-1 等)
  3. ColorMap.json - 这是两者的结合
  4. 构建阶段脚本以获取 ColorSystem.json 和 ColorMap.json 并将两者结合以生成一个新的 Colors.xcassets 系统。

然后每当我们改变十六进制时,我们就改变ColorMap.json。每当我们更改语义颜色以使用不同的“真实”颜色时,我们都会更改 ColorMap.json.

也许我误解了你的确切问题,但是你如何将你的颜色类型添加到你的资产中。这些通常被定义为“主要”“次要”等。但您可以将它们添加为“red1”、“red2”等。

然后在代码中,您可以在 UIColor 扩展中设置这些资产,例如:

extension UIColor {
    // MARK: Colors set in assets folder
    static var red1: UIColor {
        UIColor(named: "red1") ?? .red // Named returns an optional, so default
    }

    static var red2: UIColor {
        UIColor(named: "red1") ?? .red // Named returns an optional, so default
    }

    static var black1: UIColor {
        UIColor(named: "black1") ?? .black
    }

    // MARK: - My predefined colors
    static var primaryBackground: UIColor {
        .red1
    }

    static var primaryText: UIColor {
        .black1
    }

    static var highlightedText: UIColor {
        .red1
    }

    static var secondaryBackground: UIColor {
        .red2
    }
}

red1red2 的黑暗模式值等您将在资产文件夹中定义。

现在在您的代码中,您只需按以下方式访问它们:

override func viewDidLoad() {
  super.viewDidLoad()
  view.backgroundColor = .primaryBackground
}

更新 不同模式的不同颜色处理在资产目录中完成。在下面的示例中,它被称为“Background primary”而不是“red1”;但你可以随便称呼它。 您可以根据品牌的颜色配置文件(声明主要、次要行为)定义资产目录中的颜色,或者定义您在此处使用的颜色(例如红色、黄色、绿色行为),然后在您的代码如上所述。

第一种是“正确”的做法,因为您将定义在应用程序中重复使用的类别。例如,在亮模式下将背景设置为红色,在暗模式下设置为绿色,您将 select 应用程序中的“背景”颜色,而不是红色或绿色。

做资产目录所做的事情,而不实际使用资产目录。使用 UIColor 动态提供程序初始化程序将您的颜色完全在代码中定义为亮/暗模式对:

https://developer.apple.com/documentation/uikit/uicolor/3238041-init

现在继续在整个应用程序中使用这些颜色。无需知道您是处于亮模式还是暗模式。不需要“开销”。您的颜色将自动始终适合当前模式,并会在用户在明暗模式之间切换时自动更改。