Мне нравится использовать цвета как константы, например Color(.primaryColor), а не текстовые имена, например Color("primary_color"). Это быстрее, меньше шансов ошибиться, и можно быстро провести рефакторинг, глобально переименовав название цвета во всем коде.
Перебирая возможные решения для упрощения работы с цветами, я решил, что не хочу использовать Swift R для этих целей по ряду причин. Я также не планирую использовать Storyboard или Xib-файлы. Поэтому я решил хранить цвета в коде.
Я не мог найти стандартный простой способ создания динамического цвета с помощью кода, который будет автоматически меняться в зависимости от текущей цветовой схемы в режиме реального времени.
Позже я нашел механизм в UIColor, который позволяет мне сделать задуманное, и сделал инициализатор на его основе.
Инициализатор, принимающий цвета как UIColor, будет удобен для лаконичной записи с литералами цветов:
extension Color {
init(_ unspecifiedColor: UIColor,
dark darkColor: UIColor,
light lightColor: UIColor? = nil) {
self = Color(UIColor {
switch $0.userInterfaceStyle {
case .unspecified:
return unspecifiedColor
case .dark:
return darkColor
case .light:
return lightColor ?? unspecifiedColor
@unknown default:
return unspecifiedColor
}
})
}
}
Пример использования с литералами цвета:
extension Color {
// Вместо 🟩 & 🟥 используйте что-то вроде этого:
// #colorLiteral(red: 0, green: 1, blue: 0, alpha: 1).
// Комментирование кода с помощью ``//``
// будет переключаться между ``🟩`` и ``#colorLiteral(...)``.
static let primaryColor = Color(🟩, dark: 🟥)
}
Инициализатор, принимающий цвета как SwiftUI.Color, тоже пригодится:
extension Color {
init(_ unspecifiedColor: Color,
dark darkColor: Color,
light lightColor: Color? = nil) {
let lightUIColor = lightColor.map { UIColor($0) }
self.init(UIColor(unspecifiedColor),
dark: UIColor(darkColor),
light: lightUIColor)
}
}
Пример использования с константами:
extension Color {
static let primaryColor = Color(.red, dark: .blue)
}
Демо-приложение:
extension Color {
static let primaryColor = Color(🟩, dark: 🟥)
}
@main
struct DynamicColorApp: App {
@State var colorSheme: ColorScheme = .light
var body: some Scene {
WindowGroup {
VStack {
Text("Green by day and red by night")
.foregroundColor(.primaryColor)
Button("light") {
colorSheme = .light
}
Button("dark") {
colorSheme = .dark
}
}
.preferredColorScheme(colorSheme)
}
}
}
Результат:
Буду рад ответить на комментарии, если есть какие-либо замечания или идеи по этому решению.
Спасибо за внимание ❤️🤖
