7
votes

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)
2
primary and secondary are really foreground colors. Have you tried using colorInvert on primary or secondary for your background?Michael Salmon
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

2 Answers

9
votes

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/

7
votes

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)    
    }
}