Search code examples
ioscolorsbackground-colorios-darkmode

Custom elevated background color for iOS dark mode


In the dark mode section of the Human Interface Guidelines, Apple describes that there is basically three background colors when you use the system background - light, dark, and dark elevated (which is used for modals, for example).

Is there any way to use this elevated style for custom colors? I have a custom background color in my Assets file which includes light and dark mode, but for elevated content it will still use the dark mode color.


Solution

  • Thanks Kurt Revis for pointing my to this. I was able to do this using a special UIColor initializer that Swift provides. The only downside is that this will not work in interface builder (since it is not baked into the Asset itself), but in code this will work perfectly:

    class ElevatedColor: UIColor {
        convenience init(regular: UIColor, elevated: UIColor) {
            if #available(iOS 13.0, *) {
                self.init { (traitCollection: UITraitCollection) -> UIColor in
                    let isElevated = (traitCollection.userInterfaceLevel == .elevated)
                    return isElevated ? elevated : regular
                }
            } else {
                self.init(cgColor: regular.cgColor)
            }
        }
    }
    

    This uses UIColor.init(dynamicProvider:). iOS will call the provided block whenever the interface traits change, so the color automatically updates when switching to an elevated context. Unfortunately, because of the way UIColor works, you can only make the initializer a convenience initializer, so technically you could create an ElevatedColor without an elevated version, but for me this is acceptable.