SwiftUI Color(一)

颜色作为一个App重要的组成,需要被认真地对待。在App开发中,通常情况下,我们需要用到颜色的地方,比如背景色,比如字体颜色。

在SwiftUI中,颜色是Color。它既可以很简单,也可以很复杂。比如给一个视觉元素设置背景色为白色,可以:

swift 复制代码
VStack {
	Text("Hello World")
}
.background(.white)

看似很简单,然而需要考虑的东西还不少。比如Dark Mode下,这个页面看起来应该是如何的。 因为Text没有设置字体颜色,所以使用的是系统默认的颜色。这颜色在Light Mode下是黑色,而在Dark Mode下则是白色。 因此,上面的页面,在Dark Mode下就看不到文字了。(我就吃过这个亏,上架审核的时候,说我的App在Dark Mode下不能正常使用。) 那要如何改呢? 这里要用到colorScheme。这个是一个环境变量,表示当前页面是Light Mode还是Dark Mode。 比如上面的代码就可以改成:

swift 复制代码
VStack {
	Text("Hello World")
}
.background(colorScheme == .light ? .white : .black)

这样的做法固然没错,也很直接。但试想一下,如果一个App里每个涉及到Color的地方,都要进行这样的判断,那代码简直不忍直视。而且如果有地方忽略了,那就会给用户造成不好的体验。 UIColor可以使用public init(dynamicProvider: @escaping (UITraitCollection) -> UIColor)根据Light或者Dark创建实例,达到自动适应Dark Mode的问题。 SwiftUI中是否有这样的方法呢?其实是有的。比如Color.primary,就会根据colorScheme改变颜色。当Light Mode的时候,primary是黑色,而Dark Mode下,primary就是白色。 我们自己怎么实现这样的功能? 这需要分情况考虑。 在低于iOS 17的系统,没法直接用代码实现,需要在Assets.xcassets文件中创建color set来实现。 !\[Pasted image 20250423100215.png] 使用的时候用名称就可以取得。let background = Color("background") 这里简单提一下,重点还是放在iOS 17之后的代码实现上。 iOS 17新增了ColorResource,上面的代码可以写成let background = Color(.background),编译器会帮忙检测background是否存在。 不过iOS 17可以用纯代码实现相应的功能,纯代码的爱好者应该会更喜欢。

swift 复制代码
public struct SchemeColor: Hashable, ShapeStyle {
    public let any: Color.Resolved?
    public let light: Color.Resolved
    public let dark: Color.Resolved

    public init(
        any: Color.Resolved,
        light: Color.Resolved,
        dark: Color.Resolved
    ) {
        self.any = any
        self.light = light
        self.dark = dark
    }

    public init(
        light: Color.Resolved,
        dark: Color.Resolved
    ) {
        any = nil
        self.light = light
        self.dark = dark
    }

    public func resolve(in environment: EnvironmentValues) -> Color.Resolved {
        switch environment.colorScheme {
        case .light:
            light
        case .dark:
            dark
        @unknown default:
            any ?? light
        }
    }
}

我们引入一个SchemeColor类型,实现Hashable和ShapeStyle类型,resolve函数返回Color.Resolved,这样,就可以用SchemeColor创建Color了。 用到的是Color的

swift 复制代码
@available(iOS 17.0, macOS 14.0, tvOS 17.0, watchOS 10.0, *)

    public init<T>(_ color: T) where T : Hashable, T : ShapeStyle, T.Resolved == Color.Resolved

初始化方法。 这样上面的实现就可以变成下面这样:

swift 复制代码
let background = Color(
	SchemeColor(
		light: .init(red: 1, green: 1, blue: 1),
		dark: .init(red: 0, green: 0, blue: 0)
	)
)
swift 复制代码
VStack {
	Text("Hello World")
}
.background(Color.background)

这样代码看起来就简洁多了,不用到处都是colorScheme == .light ? .white : .black的判断。

Color包含的内容还有许多,这一篇没法完全容纳,如果想要了解更多,可以关注我下一篇文章。

相关推荐
黑化旺仔8 小时前
【OC】Runtime:类元数据、加载初始化与消息派发
开发语言·macos·ios·objective-c
songgeb8 小时前
iOS App支持设置RTL语言的实践
ios·swift·ui kit
软泡芙9 小时前
【iOS】swift启动屏显示黑屏
ios
用户693717500138410 小时前
当你向领导申请 AI 编程工具预算时,如果领导追问“能提效多少,有量化数据吗”,你该怎么回答?
android·后端·ios
Layer11 小时前
一些脱离 Mac 依赖的 Agent 操作 iPhone 实现
ios·ai编程·测试
用户693717500138412 小时前
当我说 Claude 搭配 GLM-5.3-Flash 太好用了,同事却提醒我:你可能正在失去对代码的掌控
android·后端·ios
茶底世界之下13 小时前
一键裁方会丢掉什么?用 Awaking 给园林照片做两种画幅
ios
Marco_Marco13514 小时前
定位SDK接入实战:Android/iOS/鸿蒙三端怎么选、怎么接
android·ios·harmonyos
老李IT笔记1 天前
关掉设备上的 AI 扩展:两个键各管一层,配错了等于没配
人工智能·ios·智能手机
2501_915921431 天前
iOS应用耗电测试:使用Energy Log、Keymob和Instruments进行性能监控与能源消耗分析
android·ios·小程序·https·uni-app·iphone·webview