Swift 改变颜色时更新 UIColor
Swift update UIColor when change color
我正在练习扩展和结构中的 UIColor 和 CGColor。一切正常,但我意识到如果将来我将添加 "Theme" 功能,如果我从红色更改为蓝色,如何在更改主题时更新所有 UIColor 和 CGColor?
例如,当我按下按钮将主题更改为蓝色时,它如何更新所有 UIColor / CGColor?
这是我的代码:
extension UIColor {
public class func dynamicColor(light: UIColor, dark: UIColor) -> UIColor {
return UIColor {
switch [=11=].userInterfaceStyle {
case .dark: return dark
default: return light
}
}
}
}
var themePick = "Red"
struct AiooColor {
static var tableviewerHeaderTitle: UIColor {
switch themePick {
case "Red": return UIColor.dynamicColor(light: UIColor.systemRed, dark: UIColor.systemRed)
case "Blue": return UIColor.dynamicColor(light: UIColor.systemBlue, dark: UIColor.systemBlue)
// DEFAULT WILL SET TO RED
default: return UIColor.dynamicColor(light: UIColor.systemRed, dark: UIColor.systemRed)
}
}
static var tableviewerHeaderBackground: UIColor {
switch themePick {
case "Red": return UIColor.dynamicColor(light: UIColor(red: 255/255, green: 204/255, blue: 204/255, alpha: 1), dark: UIColor(red: 30/255, green: 0/255, blue: 0/255, alpha: 1))
case "Blue": return UIColor.dynamicColor(light: UIColor(red: 204/255, green: 204/255, blue: 255/255, alpha: 1), dark: UIColor(red: 0/255, green: 0/255, blue: 30/255, alpha: 1))
// DEFAULT WILL SET TO RED
default: return UIColor.dynamicColor(light: UIColor(red: 20/255, green: 0/255, blue: 0/255, alpha: 1), dark: UIColor(red: 20/255, green: 0/255, blue: 0/255, alpha: 1))
}
}
}
假设您有以下结构来跟踪用户首选项键:
struct PreferenceKeys {
static let themeStyle = "theme_style"
}
以及以下枚举(原始类型)来描述您的主题风格:
enum ThemeStyle: Int {
case themeA = 0
case themeB
case themeC
case themeD
}
首先,我将创建一个自定义服务来管理您的主题。我们称它为 ThemeService。这将允许您存储和检索用户选择的活动主题样式。它可以像这样简单:
protocol ThemeServiceInterface {
func setThemeStyle(_ themeStyle: ThemeStyle)
func getThemeStyle() -> ThemeStyle
}
final class ThemeService: ThemeServiceInterface {
static let shared = ThemeService()
let userDefaults: UserDefaults
private init() {
self.userDefaults = UserDefaults.standard
}
func setThemeStyle(_ themeStyle: ThemeStyle) {
userDefaults.set(themeStyle.rawValue, forKey: PreferenceKeys.themeStyle)
}
func getThemeStyle() -> ThemeStyle {
let rawValue = userDefaults.integer(forKey: PreferenceKeys.themeStyle)
if let themeStyle = ThemeStyle(rawValue: rawValue) {
return themeStyle
}
return .themeA
}
}
因此,当您尝试访问特定颜色时,只需询问您的主题服务什么是活动主题样式,然后相应地设置您的颜色。
extension UIColor {
static var primaryColor: UIColor {
switch ThemeService.shared.getThemeStyle() {
case .themeA: return .systemBlue
case .themeB: return .systemRed
case .themeC: return .systemGreen
case .themeD: return .systemIndigo
}
}
static var secondaryColor: UIColor {
.systemPink
}
// ...
}
现在当你的用户想要设置一个新的主题样式时,你只需要调用下面的方法:
ThemeService.shared.setThemeStyle(.themeC)
太棒了,您所有新创建的视图都将反映新的主题样式。
但是现在到了我们需要为所有现有视图重置 UI 的部分。那么,根据项目的结构,您会有不同的选择。
例如,您可以让 ThemeService 通过 NotificationCenter
向所有屏幕发送通知,要求它们重新加载 UI(使用 setNeedsDisplay()
/ setNeedsLayout()
方法例如)
如果这听起来对您的项目来说工作量太大,另一种不错且简单的方法可能是用漂亮的动画简单地重置您的 UIWindow 的 rootViewController
,这将导致您的 UI 被重置并匹配活动主题样式。
希望对您有所帮助!
我正在练习扩展和结构中的 UIColor 和 CGColor。一切正常,但我意识到如果将来我将添加 "Theme" 功能,如果我从红色更改为蓝色,如何在更改主题时更新所有 UIColor 和 CGColor?
例如,当我按下按钮将主题更改为蓝色时,它如何更新所有 UIColor / CGColor?
这是我的代码:
extension UIColor {
public class func dynamicColor(light: UIColor, dark: UIColor) -> UIColor {
return UIColor {
switch [=11=].userInterfaceStyle {
case .dark: return dark
default: return light
}
}
}
}
var themePick = "Red"
struct AiooColor {
static var tableviewerHeaderTitle: UIColor {
switch themePick {
case "Red": return UIColor.dynamicColor(light: UIColor.systemRed, dark: UIColor.systemRed)
case "Blue": return UIColor.dynamicColor(light: UIColor.systemBlue, dark: UIColor.systemBlue)
// DEFAULT WILL SET TO RED
default: return UIColor.dynamicColor(light: UIColor.systemRed, dark: UIColor.systemRed)
}
}
static var tableviewerHeaderBackground: UIColor {
switch themePick {
case "Red": return UIColor.dynamicColor(light: UIColor(red: 255/255, green: 204/255, blue: 204/255, alpha: 1), dark: UIColor(red: 30/255, green: 0/255, blue: 0/255, alpha: 1))
case "Blue": return UIColor.dynamicColor(light: UIColor(red: 204/255, green: 204/255, blue: 255/255, alpha: 1), dark: UIColor(red: 0/255, green: 0/255, blue: 30/255, alpha: 1))
// DEFAULT WILL SET TO RED
default: return UIColor.dynamicColor(light: UIColor(red: 20/255, green: 0/255, blue: 0/255, alpha: 1), dark: UIColor(red: 20/255, green: 0/255, blue: 0/255, alpha: 1))
}
}
}
假设您有以下结构来跟踪用户首选项键:
struct PreferenceKeys {
static let themeStyle = "theme_style"
}
以及以下枚举(原始类型)来描述您的主题风格:
enum ThemeStyle: Int {
case themeA = 0
case themeB
case themeC
case themeD
}
首先,我将创建一个自定义服务来管理您的主题。我们称它为 ThemeService。这将允许您存储和检索用户选择的活动主题样式。它可以像这样简单:
protocol ThemeServiceInterface {
func setThemeStyle(_ themeStyle: ThemeStyle)
func getThemeStyle() -> ThemeStyle
}
final class ThemeService: ThemeServiceInterface {
static let shared = ThemeService()
let userDefaults: UserDefaults
private init() {
self.userDefaults = UserDefaults.standard
}
func setThemeStyle(_ themeStyle: ThemeStyle) {
userDefaults.set(themeStyle.rawValue, forKey: PreferenceKeys.themeStyle)
}
func getThemeStyle() -> ThemeStyle {
let rawValue = userDefaults.integer(forKey: PreferenceKeys.themeStyle)
if let themeStyle = ThemeStyle(rawValue: rawValue) {
return themeStyle
}
return .themeA
}
}
因此,当您尝试访问特定颜色时,只需询问您的主题服务什么是活动主题样式,然后相应地设置您的颜色。
extension UIColor {
static var primaryColor: UIColor {
switch ThemeService.shared.getThemeStyle() {
case .themeA: return .systemBlue
case .themeB: return .systemRed
case .themeC: return .systemGreen
case .themeD: return .systemIndigo
}
}
static var secondaryColor: UIColor {
.systemPink
}
// ...
}
现在当你的用户想要设置一个新的主题样式时,你只需要调用下面的方法:
ThemeService.shared.setThemeStyle(.themeC)
太棒了,您所有新创建的视图都将反映新的主题样式。
但是现在到了我们需要为所有现有视图重置 UI 的部分。那么,根据项目的结构,您会有不同的选择。
例如,您可以让 ThemeService 通过 NotificationCenter
向所有屏幕发送通知,要求它们重新加载 UI(使用 setNeedsDisplay()
/ setNeedsLayout()
方法例如)
如果这听起来对您的项目来说工作量太大,另一种不错且简单的方法可能是用漂亮的动画简单地重置您的 UIWindow 的 rootViewController
,这将导致您的 UI 被重置并匹配活动主题样式。
希望对您有所帮助!