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