Logo for tanaschita.com

Dynamic colors in SwiftUI

Learn to use the asset catalog or the programmatic approach to define dynamic colors in SwiftUI

08 Nov 2021 · 4 min read

SwiftUI offers a range of predefined semantic colors we can use in our views. But in most cases, we want to define our own custom colors that automatically adapt to certain user preferences like dark mode changes.

This can be achieved by using the asset catalog or programmatically.

Using the asset catalog to define dynamic colors for SwiftUI views

Defining dynamic colors via the asset catalog can be achieved with the following steps:

  1. Open the Assets.xcassets file that was created with the iOS project.
  2. Add colors by using the + button.
  3. Configure dark mode colors by opening the Attributes Inspector and select Any, Dark in the Appearances dialog.

After doing that, we will be presented with a new color dark mode setting.

Color Asset Catalog
Color Asset Catalog

To use the defined color in a SwiftUI view, we initialize the Color with its catalog name:

.foregroundColor(Color(named: "error"))

It will automatically adjust to dark mode changes.

The programmatic approach to define dynamic colors for SwiftUI views

To achieve the same results programmatically, we can make use of the UITraitCollection class which represents the interface environment for our iOS app.

UIColor provides an initializer that takes a closure which gets called when the interface environment like a dark mode setting changes.

public init(dynamicProvider: @escaping (UITraitCollection) -> UIColor)

Knowing that, we can create a utility method:

extension UIColor {
static func dynamicColor(light: UIColor, dark: UIColor) -> UIColor {
guard #available(iOS 13.0, *) else { return light }
return UIColor { $0.userInterfaceStyle == .dark ? dark : light }
}
}

And use it to define dynamic colors programmatically.

struct ColorScheme {
var error: Color {
return color(light: UIColor(red: 0.7, green: 0.1, blue: 0.1, alpha: 1),
dark: UIColor(red: 0.9, green: 0.1, blue: 0.1, alpha: 1))
}
private func color(light: UIColor, dark: UIColor) -> Color {
return Color(UIColor.dynamicColor(light: light, dark: dark))
}
}

SwiftUI's Color class itself does not provide the trait collection initializer, but as we can see above, we can simply convert the UIKit's UIColor to SwiftUI's Color type.

Now, we can use the created color scheme in our SwiftUI views.

.foregroundColor(colorScheme.error)
Image of books
Further reading: SwiftUI by Example
For further reading, check out the SwiftUI by Example book by Paul Hudson. It guides you through dozens of common coding problems with hands-on solutions.

Newsletter

Receive a monthly newsletter about the latest articles and tips.

Image of a reading marmot

Related tags

Written by

Articles with related topics

Latest articles and tips