Привет всем!
Долго молчу, потому что изучаю swift.
Написал gist сменных тем для приложения на SwiftUI - выбранная тема меняет интерфейс сразу и после перезапуска остается такой же, которая была выбрана (используется UserDefaults).
Исходник тут тоже положу, но за последней версией лучше идти на гитхаб https://gist.github.com/crusat/177b5bc7d206f466bd8acbd66708588c
Пример можно посмотреть здесь: https://crusat.ru/media/uploads/2020/05/24/RPReplay_Final1590305369.MP4
Файл ContentView.swift
:
import SwiftUI
struct Theme: Hashable {
var colorPrimary: Color = Color.primary
var name: String? = nil
var publicName: String = "System"
}
var themes: [Theme] = [
Theme(colorPrimary: Color.primary, name: nil, publicName: "System"),
Theme(colorPrimary: Color.purple, name: "purple", publicName: "Purple"),
Theme(colorPrimary: Color.orange, name: "orange", publicName: "Orange"),
Theme(colorPrimary: Color.red, name: "red", publicName: "Red"),
Theme(colorPrimary: Color.green, name: "green", publicName: "Green"),
Theme(colorPrimary: Color.blue, name: "blue", publicName: "Blue"),
Theme(colorPrimary: Color.pink, name: "pink", publicName: "Pink"),
Theme(colorPrimary: Color.yellow, name: "yellow", publicName: "Yellow"),
]
func getTheme(themeName: String?) -> Theme {
if themeName != nil {
for theme in themes {
if themeName! == theme.name {
return theme
}
}
}
return themes[0]
}
func getCurrentTheme() -> Theme {
let currentThemeName = UserDefaults.standard.string(forKey: "themeName")
return getTheme(themeName: currentThemeName)
}
struct ChangeThemeButton: View {
@Binding var currentThemeName: String?
var colorName: String
var themeName: String?
var body: some View {
HStack {
Button(action: {
UserDefaults.standard.set(self.themeName, forKey: "themeName")
self.currentThemeName = UserDefaults.standard.string(forKey: "themeName")
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "themeUpdated"), object: self)
}) {
HStack {
Circle()
.fill(getTheme(themeName: themeName).colorPrimary)
.frame(width: 25, height: 25)
Text(self.colorName)
if self.currentThemeName == themeName {
Image(systemName: "checkmark")
}
}
}
}
}
}
struct SelectThemeView: View {
@State var currentThemeName = UserDefaults.standard.string(forKey: "themeName")
var body: some View {
List {
ForEach(themes, id: \.self) { theme in
ChangeThemeButton(currentThemeName: self.$currentThemeName, colorName: theme.publicName, themeName: theme.name)
}
}
.navigationBarTitle("Тема").onAppear {
self.currentThemeName = UserDefaults.standard.string(forKey: "themeName")
}
}
}
struct SettingsView: View {
var body: some View {
NavigationView {
List {
NavigationLink(destination: SelectThemeView()) {
Text("Change theme")
}
}
.navigationBarTitle("Settings")
}
}
}
struct ContentView: View {
@State var currentTheme: Theme = getCurrentTheme()
@State private var selection = 0
var body: some View {
HStack {
TabView(selection: $selection){
Text("Hello, world!")
.tabItem {
VStack {
Image(systemName: "gear")
Text("Settings")
}
}
.tag(0)
SettingsView()
.tabItem {
VStack {
Image(systemName: "gear")
Text("Settings")
}
}
.tag(1)
}
}
.accentColor(currentTheme.colorPrimary)
.onAppear {
NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: "themeUpdated"), object: nil , queue: nil) { (notification) in
DispatchQueue.main.async {
self.currentTheme = getCurrentTheme()
}
}
}
}
}