How to get RGB components from Color in SwiftUI
iOS 14 / macOS 10.16
There is a new initializer that takes a Color
and returns a UIColor
for iOS or NSColor
for macOS now. With the help of those you can implement the following extensions:
iOS / macOS
import SwiftUI
#if canImport(UIKit)
import UIKit
#elseif canImport(AppKit)
import AppKit
#endif
extension Color {
var components: (red: CGFloat, green: CGFloat, blue: CGFloat, opacity: CGFloat) {
#if canImport(UIKit)
typealias NativeColor = UIColor
#elseif canImport(AppKit)
typealias NativeColor = NSColor
#endif
var r: CGFloat = 0
var g: CGFloat = 0
var b: CGFloat = 0
var o: CGFloat = 0
guard NativeColor(self).getRed(&r, green: &g, blue: &b, alpha: &o) else {
// You can handle the failure here as you want
return (0, 0, 0, 0)
}
return (r, g, b, o)
}
}
Usage
Color.red.components.red // 0.9999999403953552 // <- SwiftUI Colors are not pure!
Hex codes/RGB values for SwiftUI colors?
If you are coding in SwiftUI 2 you can convert your Color to UIColor and use getRed method to get the red, green, blue and alpha components. Once you have the components you can convert the values to hexa string:
extension Color {
var uiColor: UIColor { .init(self) }
typealias RGBA = (red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat)
var rgba: RGBA? {
var (r, g, b, a): RGBA = (0, 0, 0, 0)
return uiColor.getRed(&r, green: &g, blue: &b, alpha: &a) ? (r, g, b, a) : nil
}
var hexaRGB: String? {
guard let (red, green, blue, _) = rgba else { return nil }
return String(format: "#%02x%02x%02x",
Int(red * 255),
Int(green * 255),
Int(blue * 255))
}
var hexaRGBA: String? {
guard let (red, green, blue, alpha) = rgba else { return nil }
return String(format: "#%02x%02x%02x%02x",
Int(red * 255),
Int(green * 255),
Int(blue * 255),
Int(alpha * 255))
}
}
Color.purple.hexaRGB // "#af52de"
Color.purple.hexaRGBA // "#af52deff"
if let (red, green, blue, alpha) = Color.purple.rgba {
red // 0.686274528503418
green // 0.321568638086319
blue // 0.8705882430076599
alpha // 1
}
Get Value from SwiftUI Color Picker
In majority of cases you use Color
in SwiftUI directly, ie it is not needed to extract anything from it.
Anyway if it is needed to have UIColor
SwiftUI 2.0 provides new API for that
extension UIColor {
@available(iOS 14.0, tvOS 14.0, watchOS 7.0, *)
@available(OSX, unavailable)
public convenience init(_ color: Color)
}
How to use Color with RGB or hex value in SwiftUI using Swift 5?
The UIColor init method UIColor(red:green:blue:alpha)
takes float values from 0 to 1 for each value.
Any value ≥ 1.0 is going to "max out" that color. So an expression like UIColor(red: 220, green: 24, blue: 311, alpha: 1)
will set all 3 color channels and alpha to 1.0, resulting in white. So would UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
You could create an extension to UIColor that adds convenience initializers that would take values of different types. First, and initializer that would take values from 0-255 for each. Then you could create another intializer UIColor.init(hexString:String)
.
The one that took values from 0-255 would be a lot easier to write. The one that took hex strings would involve implementing a hex parser. I bet somebody has already written it though.
Take a look at this code, for example:
https://gist.github.com/anonymous/fd07ecf47591c9f9ed1a
How to check if a specific color is selected with SwiftUI's ColorPicker?
As @workingdog pointed out to me, the best approach to comparing colors here is converting them to a comparable system by taking their color components.
SwiftUI‘s Color type doesn‘t grant access to its components out of the box but by converting to UIColor we get methods for retrieving the color’s rgb, hsb and grayscale components.
By using this trick we can extend Color and add properties for conveniently getting the components we need in our comparisons:
extension Color {
var rgbComponents: (red: CGFloat, green: CGFloat, blue: CGFloat, opacity: CGFloat) {
var (r, g, b, a): (CGFloat, CGFloat, CGFloat, CGFloat) = (0, 0, 0, 0)
UIColor(self).getRed(&r, green: &g, blue: &b, alpha: &a)
return (r, g, b, a)
}
var hsbComponents: (hue: CGFloat, saturation: CGFloat, brightness: CGFloat, opacity: CGFloat) {
var (h, s, b, a): (CGFloat, CGFloat, CGFloat, CGFloat) = (0, 0, 0, 0)
UIColor(self).getHue(&h, saturation: &s, brightness: &b, alpha: &a)
return (h, s, b, a)
}
var grayscaleComponents: (white: CGFloat, opacity: CGFloat) {
var (w, o): (CGFloat, CGFloat) = (0, 0)
UIColor(self).getWhite(&w, alpha: &o)
return (w, o)
}
}
As I just want to check if black or white is selected for knowing when to adjust the color on theme change, getting the grayscale components is sufficient in my use case.
We can then use these components to compare the colors selected in the color picker. I found that the values generated by moving the sliders in the picker are sometimes a bit inaccurate however. For instance, selecting pure black by setting all rgb values to 0 can result in rgb components that are actually slightly above zero, possibly due to inaccurate rounding of float values. I accounted for this by comparing the component values to a small range of values respectively:
func updateColorScheme() {
// set the theme
let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene
scene?.keyWindow?.overrideUserInterfaceStyle = theme
// update the selected color
let isDarkMode = UITraitCollection.current.userInterfaceStyle == .dark
if isDarkMode && baseColor.grayscaleComponents.white < 0.0001 {
baseColor = .white
}
if !isDarkMode && baseColor.grayscaleComponents.white > 0.9999 {
baseColor = .black
}
}
Color rgb initializer not working as background in SwiftUI
It looks like it is asking for the colors in percentages, I was able to get it to work doing this
Color(red: 242 / 255, green: 242 / 255, blue: 242 / 255)
How to compare three Color in SwiftUI
I really dont undestand what you want to achieve but you can compare them like
let colorr = UIColor(red: 122/255, green: 100/255, blue: 180/255, alpha: 1.0)
let rgbColorr = colorr.cgColor
let rgbColorrs = rgbColorr.components
This rgbColorrs
prints and array like [0.47843137254901963, 0.39215686274509803, 0.7058823529411765, 1.0]
its like [red,green,blue,alpha]
if rgbColorrs[0] == rgbColors[1] == rgbColors[2]{
//....
}
Or if you want to compare equality
if UIColor.red.isEqual(UIColor.green.isEqual(UIColor.blue)){
...
}
Related Topics
Wkwebview Does Not Load Links to Pdfs
Type Conversion When Using Protocol in Swift
Why Are Doubles Printed Differently in Dictionaries
Finish Asynchronous Task in Firebase With Swift
How to Use an Nsattributedstring with a Scrollview in Swiftui
Can the Height of the Uisearchbar Textfield Be Modified
How to Get Directory Size with Swift on Os X
Swift Repl: How to Import, Load, Evaluate, or Require a .Swift File
Downloading and Caching Images from Url Asynchronously
Swift Dictionary Default Value
What Is the Swift Syntax " .Bar" Called
Distinction in Swift Between Uppercase "Self" and Lowercase "Self"
Draw Scenekit Object Between Two Points
Embedding Videos in a Tableview Cell