I want to realize a function which could change the color scheme of app.
However, whenever I click theme style in ThemeView, it will pop to SettingsView and Tab will reselect to Home.
Is there a way that I can change the color scheme of app, and still stay in ThemeView?
AppTabView.swift
public enum ThemeStyle: Int, CaseIterable {
case automatic
case light
case dark
}
extension View {
@ViewBuilder
func themeStyle(_ themeStyle: ThemeStyle) -> some View {
switch themeStyle {
case .automatic:
self
case .light:
preferredColorScheme(.light)
case .dark:
preferredColorScheme(.dark)
}
}
}
struct AppTabView: View {
@AppStorage(StorageKeys.themeStyle) private var themeStyle: ThemeStyle = .automatic
var body: some View {
TabView(selection: $tabItem) {
Text("First Tab")
.tabItem {
Label("Home", systemImage: .house)
}
NavigationView {
SettingsView()
}
.tabItem {
Label("Settings", systemImage: .gearshapeFill)
}
}
.themeStyle(themeStyle)
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
}
}
SettingsView.swift
struct SettingsView: View {
var body: some View {
List {
Section {
NavigationLink {
ThemeView()
} label: {
Label("TITLE_THEME", systemImage: .circleLefthalfFill)
}
}
.navigationTitle("TITLE_SETTINGS")
.navigationBarTitleDisplayMode(.inline)
}
}
ThemeView.swift
struct ThemeView: View {
@AppStorage(StorageKeys.themeStyle) private var themeStyle: ThemeStyle = .automatic
@ViewBuilder
private func text(_ themeStyle: ThemeStyle) -> some View {
switch themeStyle {
case .automatic:
Text("TITLE_THEME_AUTOMATIC")
case .light:
Text("TITLE_THEME_LIGHT")
case .dark:
Text("TITLE_THEME_DARK")
}
}
@ViewBuilder
private func image(_ themeStyle: ThemeStyle) -> some View {
switch themeStyle {
case .automatic:
Image(systemName: .circleLefthalfFill)
case .light:
Image(systemName: .sunMax)
case .dark:
Image(systemName: .moon)
}
}
var body: some View {
List {
ForEach(ThemeStyle.allCases, id: \.rawValue) { value in
Button {
themeStyle = value
} label: {
HStack {
Label {
text(value)
.foregroundColor(.label)
} icon: {
image(value)
}
if themeStyle == value {
Spacer()
Image(systemName: .checkmark)
}
}
}
}
}
.navigationTitle("TITLE_THEME")
.navigationBarTitleDisplayMode(.inline)
}
}