Home > database >  How to detect if Color is white or black in Swift
How to detect if Color is white or black in Swift

Time:11-28

The following code successfully detects if the color is black, but it doesn't detect when the color is white or any other color.

Any idea why the following code only works to detect black but not white?

func bgColor(bgColor: Color?)->Color{
    var col:Color = .systemBackground

    if bgColor == Color(UIColor(red: 0, green: 0, blue: 0, alpha: 1)){
        // Works fine, detects black
        col = .red
    } else if bgColor == Color(UIColor(red: 1, green: 1, blue: 1, alpha: 1)){
        // Does NOT work, doesn't detect white
        col = .blue
    }
    return col
}

EDIT:

I have a ViewModifier that I'm using on a symbol-avatar-image, in this avatar image the user can select a color from a Color Picker, my issue is that I have the .systemBackground as the default background color, and if the user selects white or black for their avatar, black is not visible in dark mode and white is not visible in light mode so, what I would like to do is detect if the user selected white, I need to return a dark background color for light mode and if the user selects black I would like to return a light background for when in dark mode.

struct AvatarImageModifier : ViewModifier {
    @Environment(\.colorScheme) var colorScheme
    var avatarColor:Color?
    
    func body(content: Content) -> some View { content
        .background(bgColor(bgColor: avatarColor))
    }
    
    func bgColor(bgColor: Color?)->Color{
        var col:Color = .systemBackground
        
        if bgColor == Color(UIColor(red: 0, green: 0, blue: 0, alpha: 1)){
            if colorScheme == .dark{
                col = .systemGray3
            }else{
                col = .systemBackground
            }
        } else if bgColor == Color(UIColor(red: 1, green: 1, blue: 1, alpha: 1)){
            if colorScheme == .light{
                col = .systemGray3
            }
        }
        return col
    }
}

CodePudding user response:

You can get the HSB brightness component from Color by first converting it to a UIColor. Here's a little extension I made to do this:

import UIKit
import SwiftUI

extension Color {
    enum Brightness {
        case light, medium, dark, transparent

        private enum Threshold {
            static let transparent: CGFloat = 0.1
            static let light: CGFloat = 0.75
            static let dark: CGFloat = 0.3
        }

        init(brightness: CGFloat, alpha: CGFloat) {
            if alpha < Threshold.transparent {
                self = .transparent
            } else if brightness > Threshold.light {
                self = .light
            } else if brightness < Threshold.dark {
                self = .dark
            } else {
                self = .medium
            }
        }
    }

    var brightness: Brightness {
        var b: CGFloat = 0
        var a: CGFloat = 0
        let uiColor = UIColor(self)
        uiColor.getHue(nil, saturation: nil, brightness: &b, alpha: &a)
        return .init(brightness: b, alpha: a)
    }
}

Color.white.brightness // .light
Color.gray.brightness  // .medium
Color.black.brightness // .dark
Color.clear.brightness // .transparent

The thresholds are ad hoc and untested for any real purpose. The Color.init used here also requires iOS 14 (https://developer.apple.com/documentation/uikit/uicolor/3550899-init).

CodePudding user response:

Here is a right way for you:

struct ContentView: View {
    
    @State private var backgroundColor: Color = Color(UIColor.systemBackground)
    @State private var avatarColor: Color = Color.green
    
    var body: some View {
        
        ZStack {
            
            backgroundColor

            VStack(spacing: 20.0) {
                
                Image(systemName: "person")
                    .font(Font.system(size: 100.0))
                    .modifier(AvatarImageModifier(avatarColor: avatarColor) { colorValue in backgroundColor = colorValue })
                
                Button("Set avatarColor to white") { avatarColor = Color.white }
                
                Button("Set avatarColor to black") { avatarColor = Color.black }
                
            }

        }
  
    }
    
}

struct AvatarImageModifier : ViewModifier {
    
    @Environment(\.colorScheme) var colorScheme
    
    let avatarColor: Color
    let backgroundColor: (Color) -> Void
    
    func body(content: Content) -> some View {
        
        content
            .foregroundColor(avatarColor)
            .preference(key: ColorPreferenceKey.self, value: avatarColor)
            .onPreferenceChange(ColorPreferenceKey.self) { newValue in

                if (newValue == Color.black) {
  
                    if (colorScheme == .dark) {
                        backgroundColor(Color(UIColor.systemGray3))
                    }
                    else {
                        backgroundColor(Color(UIColor.systemBackground))
                    }
                    
                }
                else if (newValue == Color.white) {

                    if (colorScheme == .dark) {
                        backgroundColor(Color(UIColor.systemBackground))
                    }
                    else {
                        backgroundColor(Color(UIColor.systemGray3))
                    }
                    
                }
  
            }
            .onChange(of: colorScheme, perform: { newValue in
                
                
                if (avatarColor == Color.black) {
  
                    if (newValue == .dark) {
                        backgroundColor(Color(UIColor.systemGray3))
                    }
                    else {
                        backgroundColor(Color(UIColor.systemBackground))
                    }
                    
                }
                else if (avatarColor == Color.white) {

                    if (newValue == .dark) {
                        backgroundColor(Color(UIColor.systemBackground))
                    }
                    else {
                        backgroundColor(Color(UIColor.systemGray3))
                    }
                    
                }
  
            })

    }
    
}

struct ColorPreferenceKey: PreferenceKey {
    
    static var defaultValue: Color { get { return Color.clear } }
    
    static func reduce(value: inout Color, nextValue: () -> Color) { value = nextValue() }
    
}
  • Related