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

相关推荐
他们都不看好你,偏偏你最不争气4 小时前
【iOS】UIViewController
开发语言·macos·ios·objective-c·cocoa
前端小超超9 小时前
如何配置capacitor 打包的ios app固定竖屏展示?
前端·ios·web app
CocoaKier9 小时前
AI让35岁程序员再次伟大
ios·微信小程序·aigc
库奇噜啦呼9 小时前
【iOS】单例模式
ios·单例模式
2501_915909069 小时前
苹果上架App软件全流程指南:iOS 应用发布步骤、App Store 上架流程、uni-app 打包上传与审核技巧详解
android·ios·小程序·https·uni-app·iphone·webview
2501_915921439 小时前
iOS 文件管理与能耗调试结合实战 如何查看缓存文件、优化电池消耗、分析App使用记录(uni-app开发与性能优化必备指南)
android·ios·缓存·小程序·uni-app·iphone·webview
2501_9159184110 小时前
App 苹果 上架全流程解析 iOS 应用发布步骤、App Store 上架流程
android·ios·小程序·https·uni-app·iphone·webview
库奇噜啦呼10 小时前
【iOS】UIViewController生命周期
macos·ios·cocoa
2501_9160074710 小时前
苹果上架全流程详解,iOS 应用发布步骤、App Store 上架流程、uni-app 打包上传与审核要点完整指南
android·ios·小程序·https·uni-app·iphone·webview
YungFan11 小时前
iOS26适配指南之UISlider
ios·swift