Skip to content

Instantly share code, notes, and snippets.

@crusat
Last active July 20, 2023 06:18
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save crusat/177b5bc7d206f466bd8acbd66708588c to your computer and use it in GitHub Desktop.
Save crusat/177b5bc7d206f466bd8acbd66708588c to your computer and use it in GitHub Desktop.
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()
}
}
}
}
}
@ejbills
Copy link

ejbills commented Jul 19, 2023

this is great code to build off of. thanks!

@crusat
Copy link
Author

crusat commented Jul 20, 2023

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