-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathSTAppearanceManager.swift
More file actions
105 lines (89 loc) · 3.56 KB
/
STAppearanceManager.swift
File metadata and controls
105 lines (89 loc) · 3.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
//
// STAppearanceManager.swift
// STBaseProject
//
// Created by 寒江孤影 on 2018/3/14.
//
import UIKit
import Combine
/// SDK 统一的外观模式
public enum STAppearanceMode: Equatable {
case system // 跟随系统
case light // 强制浅色
case dark // 强制深色
}
/// 负责管理 SDK 中的深浅色模式
public final class STAppearanceManager {
public static let shared = STAppearanceManager()
/// 当前生效模式(默认跟随系统)
public private(set) var currentMode: STAppearanceMode = .system {
didSet {
guard oldValue != currentMode else { return }
self.modeSubject.send(self.currentMode)
}
}
private let modeSubject = CurrentValueSubject<STAppearanceMode, Never>(.system)
/// 订阅此 publisher 以响应外观模式变化;新订阅者立即收到当前值
public var appearanceModePublisher: AnyPublisher<STAppearanceMode, Never> {
self.modeSubject.eraseToAnyPublisher()
}
private init() {}
/// 外部(宿主 App)调用此方法即可切换 SDK 内部的显示模式
/// - Parameter mode: 目标模式
public func st_apply(mode: STAppearanceMode) {
DispatchQueue.main.async {
self.currentMode = mode
}
}
/// 计算在当前配置下应该使用的 UIUserInterfaceStyle
/// - Parameter traitCollection: 参考的 trait(为空则只根据 currentMode 决定)
public func resolvedInterfaceStyle(for traitCollection: UITraitCollection?) -> UIUserInterfaceStyle {
switch currentMode {
case .system:
return traitCollection?.userInterfaceStyle ?? .unspecified
case .light:
return .light
case .dark:
return .dark
}
}
/// 是否应展示深色内容
/// - Parameter traitCollection: 参考的 trait
public func shouldUseDarkAppearance(for traitCollection: UITraitCollection?) -> Bool {
let style = resolvedInterfaceStyle(for: traitCollection)
if currentMode == .system && style == .unspecified {
return traitCollection?.userInterfaceStyle == .dark
}
return style == .dark
}
/// 创建一个与 SDK 外观联动的动态颜色(可用于代码/XIB/SwiftUI)
public func dynamicColor(light: UIColor, dark: UIColor) -> UIColor {
return UIColor { [weak self] trait in
guard let self = self else { return light }
return self.shouldUseDarkAppearance(for: trait) ? dark : light
}
}
/// 创建一个与 SDK 外观联动的动态图片
/// - Parameters:
/// - light: 浅色图片
/// - dark: 深色图片(可为空,默认为浅色图)
public func dynamicImage(light: UIImage?, dark: UIImage?) -> UIImage? {
guard let light = light else { return dark }
let asset = UIImageAsset()
asset.register(light, with: UITraitCollection(userInterfaceStyle: .light))
asset.register((dark ?? light), with: UITraitCollection(userInterfaceStyle: .dark))
let style = resolvedInterfaceStyle(for: nil)
let trait = UITraitCollection(userInterfaceStyle: style == .unspecified ? .light : style)
return asset.image(with: trait)
}
}
#if canImport(SwiftUI)
import SwiftUI
public extension Color {
/// 根据 SDK 外观生成 Color
static func st_dynamic(light: UIColor, dark: UIColor) -> Color {
let uiColor = STAppearanceManager.shared.dynamicColor(light: light, dark: dark)
return Color(uiColor)
}
}
#endif