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类型,实现HashableShapeStyle类型,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包含的内容还有许多,这一篇没法完全容纳,如果想要了解更多,可以关注我下一篇文章。

相关推荐
开心就好20253 小时前
免 Xcode 的 iOS 开发新选择?聊聊一款更轻量的 iOS 开发 IDE kxapp 快蝎
后端·ios
恋猫de小郭6 小时前
Apple 的 ANE 被挖掘,AI 硬件公开,宣传的 38 TOPS 居然是"数字游戏"?
前端·人工智能·ios
东坡肘子10 小时前
OpenClaw 不错,但我好像没有那么需要 -- 肘子的 Swift 周报 #125
人工智能·swiftui·swift
忆江南1 天前
iOS 深度解析
flutter·ios
没有故事的Zhang同学1 天前
05-主题|事件响应者链@iOS-应用场景与进阶实践
ios
FeliksLv1 天前
尝试给Lookin 支持 MCP
ios
没有故事的Zhang同学1 天前
01-研究系统框架@Web@iOS | JavaScriptCore 框架:从使用到原理解析
ios
CocoaKier3 天前
苹果谷歌商店:如何监控并维护用户评分评论
ios·google·apple
iOS日常3 天前
iOS设备崩溃日志获取与查看
ios·xcode
wangruofeng3 天前
AI 助力 Flutter 3.27 升级到 3.38 完整指南:两周踩坑与实战复盘
flutter·ios·ai编程