持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第1天,点击查看活动详情
大家好,我是 new_cheng
。
我们在开发 swiftui 的时候,虽然 swiftui 默认支持深色模式,对于一些基本的视图,比如文字,背景都有默认的深色模式样式。
但是为了提高用户体验,一般还需要适配深色模式。而对于深色模式的适配,不应在开发完应用后,再去考虑往应用中加入深色模式,应该在开发的初期就做好规划,在开发过程中就可以边开发边测试深色模式的显示效果。
那既然要适配深色模式,在 swiftui 中,我们该采用什么方式来做呢?
有 2 种常用的的编码方案可以去适配深色模式。
1. UIColor 适配深色模式
可以通过扩展 UIColor 的方式来使用颜色,我们只需要简单的桥接 UIColor。
extension UIColor {
convenience init(light: UIColor, dark: UIColor) {
self.init { traitCollection in
switch traitCollection.userInterfaceStyle {
case .light, .unspecified:
return light
case .dark:
return dark
@unknown default:
return light
}
}
}
}
extension Color {
// 再定义一个颜色
static let defaultBackground = Color(light: .white, dark: .black)
init(light: Color, dark: Color) {
self.init(UIColor(light: UIColor(light), dark: UIColor(dark)))
}
}
// 使用
Text("文字").foregroundColor(Color.defaultBackground)
2. 使用 Assets.xcassets 适配深色模式
Assets.xcassets 允许我们定义 Color Set,一个 Color Set 包含深色模式和浅色模式所显示的颜色,我们可以定义多个 Color Set,比如文本,背景,图表等等;通过在 UI 中使用不同的颜色就能实现深色模式的适配,下面来看看具体的操作。
定义 Color Set
在 swiftui 项目选择 -> Assets.xcassets -> 右键 -> New Color Se -> 设置名称
左边的颜色(Any Appearance)默认就是浅色模式显示的颜色,右边如图所示就是深色模式显示的颜色。
选择颜色,我们就可以设置颜色的具体色值,Xcode 提供了几种颜色的设置方式,这里选择 RGB 即可。
在这里,我们定义了一个名为 textColor
的 Color Set,下一步我们会将其应用到代码中。
扩展 Color
为了更方便的使用的我们定义的颜色集,我们可以扩展 Color。
创建一个名为 Color.swift 的文件:
import Foundation
import SwiftUI
public extension Color {
static let textColor = Color("textColor")
}
对于使用 Color 作为参数的修饰符,比如 foregroundColor,background,我们就可以很方便的直接通过颜色名称来使用:
import SwiftUI
struct DetailHome: View {
var body: some View {
Text("姓名").foregroundColor(.textColor)
}
}
xcode 会提供代码编写提示。
在 xcode 的预览中,将颜色模式设置为 dark appearance,就能查看效果。
3. 固定的颜色模式
当我们不想适配深色模式,我们可以锁死颜色模式,不管系统当前的设置是深色模式还是浅色模式,我们都只固定使用某一种颜色模式。
修改项目的 info.plist
文件,添加一条 Appearance
配置,value 为 Dark,App 将会默认使用深色模式,value 为 Light,将会默认使用浅色模式。
4. 编码控制深色模式
当你希望在代码中细粒度的控制颜色时,可以通过 colorScheme 环境变量来实现。
import SwiftUI
struct DetailHome: View {
@Environment(\.colorScheme) var colorScheme: ColorScheme
var body: some View {
Text((colorScheme == .dark) ? "暗黑模式" : "浅色模式")
}
}
5. 手动切换深色模式
想要让用户手动控制应用的颜色模式,我们可以提供一个设置页面。
创建一个 AppSetting.swift
文件,用于检测和存储当前应用显示的颜色模式。
这里我们用到了 UserDefaults,这是用户默认数据库的接口,一般用于存储用户信息、App 设置等基础信息,但不宜用于存储大量数据。
当用户在系统、深色、浅色3个选项之间切换的时候,我们会获取到对应的值并赋值给 darkModeSettings,从而去设置 window.overrideUserInterfaceStyle 来改变应用的颜色模式。
此方式只会影响 window 及其所有子视图和子视图控制器。
import SwiftUI
class AppSetting: ObservableObject {
@Published var darkModeSettings: Int = UserDefaults.standard.integer(forKey: "darkMode") {
didSet {
UserDefaults.standard.set(**self**.darkModeSettings, forKey: "darkMode")
let scenes = UIApplication.shared.connectedScenes
let windowScene = scenes.first **as**? UIWindowScene
let window = windowScene?.windows.first
switch self.darkModeSettings {
case 0:
window?.overrideUserInterfaceStyle = .unspecified
case 1:
window?.overrideUserInterfaceStyle = .light
case 2:
window?.overrideUserInterfaceStyle = .dark
default:
window?.overrideUserInterfaceStyle = .unspecified
}
}
}
}
用户设置深色模式页面:
import SwiftUI
struct MyDarkModel: Identifiable {
let id: Int
let image: String
let name: String
}
struct Test2: View {
@Environment(\.colorScheme) **var** colorScheme: ColorScheme
@EnvironmentObject **var** appSettings: AppSetting
let darkModel: [MyDarkModel] = [
MyDarkModel(id: 0, image: "img_dark_auto", name: "系统"),
MyDarkModel(id: 1, image: "img_dark_off", name: "浅色"),
MyDarkModel(id: 2, image: "img_dark_on", name: "深色"),
]
var body: some View {
VStack() {
List {
Section {
HStack(spacing: 0) {
ForEach(darkModel) { item in
Button (action: {
// 点击按钮时传递颜色模式的值
appSettings.darkModeSettings = item.id
}) {
if appSettings.darkModeSettings == item.id {
Text(item.name)
.padding(.horizontal, 24)
.padding(.vertical, 12)
.foregroundColor(
appSettings.darkModeSettings == item.id ?
Color.white :
Color.primary)
.background(appSettings.darkModeSettings == item.id ?
Color.blue :
Color.white)
.cornerRadius(20)
} else {
Text(item.name)
.padding(.horizontal, 24)
.padding(.vertical, 12)
.foregroundColor(Color.primary)
}
}
.buttonStyle(BorderlessButtonStyle())
if item.id < 2 {
Spacer()
}
}
}
.padding(.horizontal, 4)
.padding(.vertical)
}
Text((colorScheme == .dark) ? "暗黑模式" : "浅色模式")
}
}
}
}
struct Test2_Previews: PreviewProvider {
static var previews: some View {
Test2().environmentObject(AppSetting())
}
}
总结
通过本文,我们学会了如果去适配深色模式,掌握了 Color Set、overrideUserInterfaceStyle 等使用,还有如何支持用户手动切换颜色模式。对于深色模式的适配,推荐采用 Assets.xcassets 的方式去定义一个完整的颜色集来适配。
这是 SwiftUI 开发之旅专栏的文章,是 swiftui 开发学习的经验总结及实用技巧分享,欢迎关注该专栏,会坚持输出。同时欢迎关注我的个人公众号 @JSHub:提供最新的开发信息速报,优质的技术干货推荐。或是查看我的个人博客:Devcursor。
👍点赞:如果有收获和帮助,请点个赞支持一下!
🌟收藏:欢迎收藏文章,随时查看!
💬评论:欢迎评论交流学习,共同进步!