New UI Element colors in SwiftUI

Is there an easy way to get the new adaptive UI element colors (systemBackground, secondaryLabel, etc.) in SwiftUI? I know that I could write a class to bridge to UIColor and do the getRed(green:blue:alpha:) dance, but it seems like there should be a simpler approach.


I know understand that these colors are used automatically in some cases, but it seems like custom controls would benefit from having them available. Am I misunderstanding the role of the UI element colors in SwiftUI?


—Chris

Post not yet marked as solved Up vote post of claurel Down vote post of claurel
7.3k views

Replies

I've filed feedback on this. The more people who do that the better.

Color.primary seems to give the system foreground, and Color.secondary gives the secondary label color, but I haven’t figured out system background yet.

I faced the same issue that the new systemColors are not available on swiftUI. Also defining colors for darkmode in asset catalog do not work.


I ended up creating a custom swiftUI view that use UIColor instead of SwiftUI.Color.


import SwiftUI

struct BackgroundView : UIViewRepresentable {
    
    var color: UIColor = .systemBackground
    
    func makeUIView(context: Context) -> UIView {
        UIView(frame: .zero)
    }
    
    func updateUIView(_ view: UIView, context: Context) {
        view.backgroundColor = color
    }
    
}

#if DEBUG
struct BackgroundView_Previews : PreviewProvider {
    static var previews: some View {
        BackgroundView(color: UIColor.systemBackground)
    }
}
#endif


Since the .background modifier will take a swiftUI view you can simply use this BackgroundView


Text("Some Text")
     .background(BackgroundView(color: .systemRed))

Color.clear seems to be the way to get systemBackground color. It's white in light mode and dark in dark mode.

Hi dsabanin. No, Color.clear is not the way to go. Color.clear is just transparent. If you draw a rectangle with Color.clear over a read area, it will be read. I just so happens that during light mode, the default background is white and in dark is black. and using Color.clear just lets it through.

Good to know, thanks!

Any progress on this? I could really use these colors. Currently I need separatorColor.

You can initialize a SwiftUI Color with a UIColor instance:


let secondaryBackground = Color(UIColor.secondarySystemBackground)


As I understand it, Color.primary maps to primaryLabel, and Color.secondary is UIColor.secondaryLabel.

I guess we all would agree that this should be provided by the system so that there is no need of writing some transformation layer from UIColor to Swift.Color.
Meanwhile, I created a swift package that provides all the available colors for SwiftUI. To do this, I used UIColor documentation and transformed it with some regexes. Under the hood, it does the conversion like:
Code Block
Color(UIColor.secondaryLabel)

You can easily add it to your project as a SwiftPM dependency in Xcode from GitHub: https://github.com/diniska/swiftui-system-colors. Let me know your thoughts about that.

My lazy solution was just adding the colors from UIKit as colors to my asset collection and calling them from there. For example, in a foregroundColor modifier, I would use this: .foregroundColor(Color("backgroundColor")) This works reasonably well for me.