SwiftUI: Using Color Set from Asset Catalog
Asked Answered
M

6

39

In SwiftUI, we can get a color from a color set in an asset catalog using:

extension Color {
    static let coral = Color("coral")
}

This requires stringly-typed names and gets quite tedious with many color sets. Is there another way to get color sets similar to how we use image literals to get images from an asset catalog? Or, just something less redundant.

If not, how are dynamic colors programmatically created in SwiftUI? For example, this is how it would be done in UIKit:

extension UIColor {
    static let dynamicColor = UIColor { $0.userInterfaceStyle == .dark ? .black : .white }
}
Medication answered 30/6, 2019 at 10:22 Comment(0)
H
4

If not, how are dynamic colors programmatically created in SwiftUI? For example, this is how it would be done in UIKit:

this can be almost the same:

extension Color {
    static let dynamicColor = Color(UIColor { traitCollection in
        return traitCollection.userInterfaceStyle == .dark ? .black : .white
    })
}
Huba answered 26/6, 2020 at 3:36 Comment(4)
This is a nice interim solution that deserves an upvote. It'd be ideal if we didn't need to lean on UIKit for this in the future.Medication
@JWK, it is official public API, so until it is deprecated (and so replaced with some new) it is valid for all scenarios.Huba
Sure, I didn't mean to imply otherwise.Medication
Realizing that you did answer the second part of this question, I'll mark it as accepted. It'd been collecting dust for a while, so I apologize for overlooking that.Medication
S
38

I want to share an alternative way to define dynamic colors in Asset catalog, but no need to write tedious code like

Color("yellow")

1. Define your color in asset catalog as usual

enter image description here

2. In your code, find a place to define your color as a variable, in my case it'll be something like this:

extension Color {
    static let ui = Color.UI()
    
    struct UI {
         let yellow = Color("yellow")
    }
}

3. Finish

Use your color like this:

Text("Hello").background(Color.ui.yellow)

This only requires writing hard-coded color in your code for only 1 time.

Schreibe answered 28/11, 2020 at 5:42 Comment(1)
you can remove static let ui = Color.UI() if you set static in front of let yellow, and then you won't have to get an instance of UI when you want a colorCatmint
B
13

It's easiest to just add an extension to Color

extension Color {
    static let primary = Color("Primary")
    static let secondary = Color("Secondary")
}

And then it's easy to use

Text("My Primary Color")
     .foregroundColor(.primary)

If you need to use it as a UIColor then do the extension on UIColor and change implementation to

Text("My Primary UIColor")
     .foregroundColor(Color(uiColor: .primary))
Beatific answered 20/3, 2022 at 19:36 Comment(0)
S
6

Finally, as of XCode 15( WDCC23 What's new in XCode 15), now asset catologs support type safety and we can access the color just by names.

.background(.poppiesOrange)

where poppiesOrange is defined a color in asset catalogs. If you also defined the dark color in the assets it will switch automatically.

Otherwise use below with @Environment(\.colorScheme) var colorScheme

.background(colorScheme == .light ? .poppiesOrange : .poppiesOrangeDark)
Satiny answered 11/6, 2023 at 20:1 Comment(1)
This should be the accepted answer by nowPicoline
H
4

If not, how are dynamic colors programmatically created in SwiftUI? For example, this is how it would be done in UIKit:

this can be almost the same:

extension Color {
    static let dynamicColor = Color(UIColor { traitCollection in
        return traitCollection.userInterfaceStyle == .dark ? .black : .white
    })
}
Huba answered 26/6, 2020 at 3:36 Comment(4)
This is a nice interim solution that deserves an upvote. It'd be ideal if we didn't need to lean on UIKit for this in the future.Medication
@JWK, it is official public API, so until it is deprecated (and so replaced with some new) it is valid for all scenarios.Huba
Sure, I didn't mean to imply otherwise.Medication
Realizing that you did answer the second part of this question, I'll mark it as accepted. It'd been collecting dust for a while, so I apologize for overlooking that.Medication
C
2

Here's another method:

import SwiftUI

enum AssetsColor : String
{
    case assetColorA
    case assetColorB
}

extension Color
{
    static func uiColor(_ name: AssetsColor) -> Color
    {
        return Color(name.rawValue)
    }
}

...

.backgroundColor(Color.uiColor(.assetColorA))
Chelate answered 14/2, 2022 at 18:40 Comment(0)
A
0

I'm pretty sure Apple will leave this to developers. For example you can write custom SwiftGen (or wait just a little) template for SwiftUI colors. https://github.com/SwiftGen/SwiftGen#colors

Ackler answered 5/8, 2019 at 21:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.