Skip to content

Instantly share code, notes, and snippets.

@crusat
Last active Apr 11, 2021
Embed
What would you like to do?
Changable themes in SwiftUI
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("Theme").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: "folder")
Text("Hello")
}
}
.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()
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment