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

相关推荐
徐赛俊2 小时前
IOS快捷指令:一键静音 / 恢复
ios
2501_915918415 小时前
常见 iOS 抓包工具的使用,从代理抓包、设备抓包到数据流抓包
android·ios·小程序·https·uni-app·iphone·webview
handsome09167 小时前
uniapp打包的app,报This app was built with the iOS 18.1 SDK解决方案
ios·uni-app
初级代码游戏10 小时前
iOS开发 SwiftUI 15:手势 拖动 缩放 旋转
ios·swiftui·swift
森之鸟13 小时前
iOS云打包之Shorebird
ios
GuokLiu13 小时前
260203-OpenWebUI-在Windows上和RHEL上部署Caddy的步骤+在iPhone上操作的步骤
windows·ios·iphone
2501_915921431 天前
傻瓜式 HTTPS 抓包,简单抓取iOS设备数据
android·网络协议·ios·小程序·https·uni-app·iphone
恋猫de小郭1 天前
Flutter 在 Android 出现随机字体裁剪?其实是图层合并时的边界计算问题
android·flutter·ios
2501_915918411 天前
把 iOS 性能监控融入日常开发与测试流程的做法
android·ios·小程序·https·uni-app·iphone·webview
Digitally1 天前
如何轻松地将大型音频文件从 iPhone 发送到不同的设备
ios·iphone