Last active
July 20, 2023 06:18
-
-
Save crusat/177b5bc7d206f466bd8acbd66708588c to your computer and use it in GitHub Desktop.
Changable themes in SwiftUI
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() | |
} | |
} | |
} | |
} | |
} | |
this is great code to build off of. thanks!
Thank you!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
this is great code to build off of. thanks!