SwiftUI 開發之旅:適配深色模式
theme: smartblue
持續創作,加速成長!這是我參與「掘金日新計劃 · 10 月更文挑戰」的第1天,點選檢視活動詳情
大家好,我是 new_cheng
。
我們在開發 swiftui 的時候,雖然 swiftui 預設支援深色模式,對於一些基本的檢視,比如文字,背景都有預設的深色模式樣式。
但是為了提高使用者體驗,一般還需要適配深色模式。而對於深色模式的適配,不應在開發完應用後,再去考慮往應用中加入深色模式,應該在開發的初期就做好規劃,在開發過程中就可以邊開發邊測試深色模式的顯示效果。
那既然要適配深色模式,在 swiftui 中,我們該採用什麼方式來做呢?
有 2 種常用的的編碼方案可以去適配深色模式。
1. UIColor 適配深色模式
可以通過擴充套件 UIColor 的方式來使用顏色,我們只需要簡單的橋接 UIColor。
```swift 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))) } } ```
swift
// 使用
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 的檔案:
```swift import Foundation import SwiftUI
public extension Color {
static let textColor = Color("textColor")
} ```
對於使用 Color 作為引數的修飾符,比如 foregroundColor,background,我們就可以很方便的直接通過顏色名稱來使用:
```swift 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 環境變數來實現。
```swift 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 及其所有子檢視和子檢視控制器。
```swift 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 } } } } ```
使用者設定深色模式頁面:
```swift 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。
👍點贊:如果有收穫和幫助,請點個贊支援一下!
🌟收藏:歡迎收藏文章,隨時檢視!
💬評論:歡迎評論交流學習,共同進步!