10

I'm trying to utilize the light & dark mode in SwiftUI, but I am struggling to get an elevated color that fits for both light and dark mode. Such as the SystemGray(0-6) colors that Apple showcased.

I have attempted to use .background(Color.primary/secondary) on my VStack or HStack and it doesn't seem to get a nice color. It's either black or dark gray. There doesn't seam to be the tertiary or quaternary colors that Apple talked about. How would I get the color of the app to match the health app? Light grey screen background with white backgrounds for the buttons in light mode and then in dark mode have a black background and dark gray buttons?

Currently, in my code below, I am using a blue background just for testing as primary/secondary does not work. Has anyone found a way to get this working properly?

VStack {
    Text("8:20").fontWeight(.semibold).font(.system(size: 80)).foregroundColor(.primary)
    Text("Hours worked").font(.body).foregroundColor(.secondary)
}
.padding()
.background(Color.blue)
.cornerRadius(15)
.shadow(radius: 10)
McKinley
  • 1,123
  • 1
  • 8
  • 18
Layne Trout
  • 105
  • 1
  • 1
  • 8
  • primary and secondary are really foreground colors. Have you tried using colorInvert on primary or secondary for your background? – Michael Salmon Aug 19 '19 at 04:08
  • 1
    UIColor defines a number of system colours e.g. systemBackground and there is a Color initialiser using UIColor so that you can get the colours you want indirectly. – Michael Salmon Aug 19 '19 at 09:38

3 Answers3

10

Looks like SwiftUI Color class has a limited amount of colours, it seems incomplete. I needed the default background colour so I could add some transparency.

The UIColor class has systemBackground which was exactly what I needed. I was able to solve my problem using this:

VStack(){ /** Code here **/}.background(Color(UIColor.systemBackground).opacity(0.95))

You might find more colours that fit what you want in UIColor. https://developer.apple.com/design/human-interface-guidelines/ios/visual-design/color/

Daniel Ryan
  • 6,976
  • 5
  • 45
  • 62
  • 1
    Great idea. Weird that SwiftUI doesn't have an accessor for this directly, but using UIColor as the basis is a smart workaround. – TheNeil Nov 24 '19 at 15:43
8

I may be misunderstanding your issue, but are you asking about determining if the device is in light or dark mode? (Your sample code works the same in both modes)? If so, have you tried using the Environment variable colorScheme?

@Environment (\.colorScheme) var colorScheme:ColorScheme

And an example on usage for theming:

extension Color {
    static let blue = Color.blue
    static let yellow = Color.yellow

    static func backgroundColor(for colorScheme: ColorScheme) -> Color {
        if colorScheme == .dark {
            return yellow
        } else {
            return blue
        }
    }
}

struct ContentView: View {
    @Environment (\.colorScheme) var colorScheme:ColorScheme
    var body: some View {
        VStack
        {
            Text("8:20").fontWeight(.semibold).font(.system(size: 80)).foregroundColor(.primary)
            Text("Hours worked").font(.body).foregroundColor(.secondary)
        }
        .padding()
        .background(Color.backgroundColor(for: colorScheme))
        .cornerRadius(15)
        .shadow(radius: 10)    
    }
}
0

The best solution for this case is to derive system color from UIColor.

Color(uiColor: UIColor.systemGray6)

If you need custom theme dependent color you can configure a custom color set in Assets.xcassets. There you can define one color for light mode and a different color for dark mode. Then just use this color set name throughout your app as you would with any other color name.

In Assets.xcassets, click the + at the bottom and then "New Color Set". Give your color a name. In "Appearances" within the attributes inspector, select "Any, Dark" You can then set a different color for each and then use it's name as your color in your app.

Paul B
  • 3,989
  • 33
  • 46