admin管理员组文章数量:1122832
When I retrieve the accent
color programmatically, it returns the accent color in the light mode. However, when I retrieve the color alone, it returns the correct color. How can I resolve this issue?
import SwiftUI
extension Color {
// Function to get RGB components from Color
private func getRGBA() -> (red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) {
let uiColor = UIColor(self)
var red: CGFloat = 0
var green: CGFloat = 0
var blue: CGFloat = 0
var alpha: CGFloat = 0
uiColor.getRed(&red, green: &green, blue: &blue, alpha: &alpha)
return (red, green, blue, alpha)
}
// Generate array of colors between two colors
static func colorRange(from startColor: Color, to endColor: Color, count: Int) -> [Color] {
guard count > 1 else { return [startColor] }
let start = startColor.getRGBA()
let end = endColor.getRGBA()
let redDelta = end.red - start.red
let greenDelta = end.green - start.green
let blueDelta = end.blue - start.blue
let alphaDelta = end.alpha - start.alpha
return (0 ..< count).map { step in
let progress = CGFloat(step) / CGFloat(count - 1)
let red = start.red + redDelta * progress
let green = start.green + greenDelta * progress
let blue = start.blue + blueDelta * progress
let alpha = start.alpha + alphaDelta * progress
return Color(UIColor(red: red, green: green, blue: blue, alpha: alpha))
}
}
}
struct ColorRangeExamples: View {
var body: some View {
VStack(spacing: 30) {
Color.accent.frame(height: 100).cornerRadius(10)
// Example 1: 5 colors between accent and secondary
let example1 = Color.colorRange(from: .accent, to: .secondary, count: 5)
HStack(spacing: 0) {
ForEach(0 ..< example1.count, id: \.self) { index in
example1[index]
}
}
.frame(height: 50)
.cornerRadius(10)
}
.padding()
}
}
#Preview {
ColorRangeExamples()
}
When I retrieve the accent
color programmatically, it returns the accent color in the light mode. However, when I retrieve the color alone, it returns the correct color. How can I resolve this issue?
import SwiftUI
extension Color {
// Function to get RGB components from Color
private func getRGBA() -> (red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) {
let uiColor = UIColor(self)
var red: CGFloat = 0
var green: CGFloat = 0
var blue: CGFloat = 0
var alpha: CGFloat = 0
uiColor.getRed(&red, green: &green, blue: &blue, alpha: &alpha)
return (red, green, blue, alpha)
}
// Generate array of colors between two colors
static func colorRange(from startColor: Color, to endColor: Color, count: Int) -> [Color] {
guard count > 1 else { return [startColor] }
let start = startColor.getRGBA()
let end = endColor.getRGBA()
let redDelta = end.red - start.red
let greenDelta = end.green - start.green
let blueDelta = end.blue - start.blue
let alphaDelta = end.alpha - start.alpha
return (0 ..< count).map { step in
let progress = CGFloat(step) / CGFloat(count - 1)
let red = start.red + redDelta * progress
let green = start.green + greenDelta * progress
let blue = start.blue + blueDelta * progress
let alpha = start.alpha + alphaDelta * progress
return Color(UIColor(red: red, green: green, blue: blue, alpha: alpha))
}
}
}
struct ColorRangeExamples: View {
var body: some View {
VStack(spacing: 30) {
Color.accent.frame(height: 100).cornerRadius(10)
// Example 1: 5 colors between accent and secondary
let example1 = Color.colorRange(from: .accent, to: .secondary, count: 5)
HStack(spacing: 0) {
ForEach(0 ..< example1.count, id: \.self) { index in
example1[index]
}
}
.frame(height: 50)
.cornerRadius(10)
}
.padding()
}
}
#Preview {
ColorRangeExamples()
}
Share
Improve this question
asked yesterday
Lê Công Minh KhôiLê Công Minh Khôi
491 silver badge6 bronze badges
0
1 Answer
Reset to default 0UIColor.getRGBA
does not respect the current color scheme.
You should use resolve(in:)
to get the RGBA values. This method takes an EnvironmentValues
which includes the color scheme information. It gives you a Color.Resolved
, from which you can directly get the RGBA values.
extension Color {
func getRGBA(env: EnvironmentValues) -> (red: Float, green: Float, blue: Float, alpha: Float) {
let resolved = resolve(in: env)
return (resolved.red, resolved.green, resolved.blue, resolved.opacity)
}
}
Similarly, colorRange
needs to take such an EnvironmentValues
parameter too.
static func colorRange(from startColor: Color, to endColor: Color, count: Int, env: EnvironmentValues) -> [Color.Resolved] {
guard count > 1 else { return [startColor.resolve(in: env)] }
let start = startColor.getRGBA(env: env)
let end = endColor.getRGBA(env: env)
let redDelta = end.red - start.red
let greenDelta = end.green - start.green
let blueDelta = end.blue - start.blue
let alphaDelta = end.alpha - start.alpha
return (0 ..< count).map { step in
let progress = Float(step) / Float(count - 1)
let red = start.red + redDelta * progress
let green = start.green + greenDelta * progress
let blue = start.blue + blueDelta * progress
let alpha = start.alpha + alphaDelta * progress
return Color.Resolved(red: red, green: green, blue: blue, opacity: alpha)
}
}
In your view, use @Environment(\.self)
to get the EnvironmentValues
.
struct ColorRangeExamples: View {
@Environment(\.self) var env
var body: some View {
VStack(spacing: 30) {
Color.accent.frame(height: 100).cornerRadius(10)
// Example 1: 5 colors between accent and secondary
let example1 = Color.colorRange(from: .accent, to: .secondary, count: 5, env: env)
HStack(spacing: 0) {
ForEach(0 ..< example1.count, id: \.self) { index in
Color(example1[index])
}
}
.frame(height: 50)
.cornerRadius(10)
}
.padding()
}
}
If you need to support earlier versions, you can use UIColor.resolvedColor(with:)
, which is similar to Color.resolve(in:)
, except it takes a UITraitCollection
. You need to implement a UIViewRepresentable
in order to get a UITraitCollection
in SwiftUI.
extension Color {
private func getRGBA(traits: UITraitCollection) -> (red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) {
let uiColor = UIColor(self).resolvedColor(with: traits)
var red: CGFloat = 0
var green: CGFloat = 0
var blue: CGFloat = 0
var alpha: CGFloat = 0
uiColor.getRed(&red, green: &green, blue: &blue, alpha: &alpha)
return (red, green, blue, alpha)
}
static func colorRange(from startColor: Color, to endColor: Color, count: Int, traits: UITraitCollection) -> [Color] {
guard count > 1 else { return [startColor] }
let start = startColor.getRGBA(traits: traits)
let end = endColor.getRGBA(traits: traits)
let redDelta = end.red - start.red
let greenDelta = end.green - start.green
let blueDelta = end.blue - start.blue
let alphaDelta = end.alpha - start.alpha
return (0 ..< count).map { step in
let progress = CGFloat(step) / CGFloat(count - 1)
let red = start.red + redDelta * progress
let green = start.green + greenDelta * progress
let blue = start.blue + blueDelta * progress
let alpha = start.alpha + alphaDelta * progress
return Color(UIColor(red: red, green: green, blue: blue, alpha: alpha))
}
}
}
struct TraitsReader<Content: View>: View {
class TraitObserver: UIView {
var traitsDidChange: ((UITraitCollection) -> Void)?
// note that this method is deprecated in iOS 17.0
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
DispatchQueue.main.async {
self.traitsDidChange?(self.traitCollection)
}
}
}
struct TraitsAccessor: UIViewRepresentable {
@Binding var traits: UITraitCollection
func makeUIView(context: Context) -> TraitObserver {
TraitObserver()
}
func updateUIView(_ uiView: TraitObserver, context: Context) {
uiView.traitsDidChange = { traits = $0 }
}
}
@ViewBuilder let content: (UITraitCollection) -> Content
@State var traits: UITraitCollection = .init()
var body: some View {
content(traits).background {
TraitsAccessor(traits: $traits)
}
}
}
struct ColorRangeExamples: View {
var body: some View {
TraitsReader { traits in
VStack(spacing: 30) {
Color.accent.frame(height: 100).cornerRadius(10)
// Example 1: 5 colors between accent and secondary
let example1 = Color.colorRange(from: .accent, to: .secondary, count: 5, traits: traits)
HStack(spacing: 0) {
ForEach(0 ..< example1.count, id: \.self) { index in
example1[index]
}
}
.frame(height: 50)
.cornerRadius(10)
}
.padding()
}
}
}
本文标签: swiftuiWrong dark mode color accentStack Overflow
版权声明:本文标题:swiftui - Wrong dark mode color accent - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736283273a1926916.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论