How to read the red, green, and blue values from a Color
How to read the red, green, and blue values from a Color 관련
Updated for Xcode 15
New in iOS 17
SwiftUI's Color
view doesn't always hold one specific color, and instead is only resolved to a specific value when it's being drawn on the screen. This allows the system to use slight variations between light and dark mode to ensure the optimal experience, but it also means the only way to get actual red, green, and blue (RGB) components out is to ask for the resolved color – ask the system “given this environment, what actual color values are being used?”
Resolving takes two steps: gaining access to the current environment, and pass that into a call to resolve(in:)
on your color. You can then save the resulting data using Codable
or whatever other data form you want.
For example, this lets the user choose any color they want, and displays its red, green, and blue components:
struct ContentView: View {
@Environment(\.self) var environment
@State private var color = Color.red
@State private var resolvedColor: Color.Resolved?
var body: some View {
VStack {
ColorPicker("Select your favorite color", selection: $color)
if let resolvedColor {
Text("Red: \(resolvedColor.red)")
Text("Green: \(resolvedColor.green)")
Text("Blue: \(resolvedColor.blue)")
Text("Opacity: \(resolvedColor.opacity)")
}
}
.padding()
.onChange(of: color, initial: true, getColor)
}
func getColor() {
resolvedColor = color.resolve(in: environment)
}
}
Important
The data is provided as Float
rather than Double
.
In that code, resolved
gets set to a Color.Resolved
type, which can be converted back into a new Color
object or be converted to JSON or similar using Codable
.
For example, we could convert our resolved color to JSON like this:
struct ContentView: View {
@Environment(\.self) var environment
@State private var color = Color.red
@State private var resolvedColor: Color.Resolved?
@State private var colorJSON = ""
var body: some View {
VStack {
ColorPicker("Select your favorite color", selection: $color)
if let resolvedColor {
Text("Red: \(resolvedColor.red)")
Text("Green: \(resolvedColor.green)")
Text("Blue: \(resolvedColor.blue)")
Text("Opacity: \(resolvedColor.opacity)")
}
Text("Color JSON: \(colorJSON)")
}
.padding()
.onChange(of: color, initial: true, getColor)
}
func getColor() {
resolvedColor = color.resolve(in: environment)
if let colorData = try? JSONEncoder().encode(resolvedColor) {
colorJSON = String(decoding: colorData, as: UTF8.self)
}
}
}
Note
We're dealing with floating-point numbers, so you can expect some microscopic variations.
If you've loaded a resolved color and want to convert it back to a Color instance, just pass it into the initializer like this:
let resolvedColor = Color.Resolved(red: 0, green: 0.6, blue: 0.9, opacity: 1)
Rectangle()
.fill(Color(resolvedColor).gradient)
.ignoresSafeArea()
A gentle blue gradient created from a resolved color.