\n
Version 1:
\nimport SwiftUI\n\nstruct ContentView: View {\n @State private var theme1 = true\n\n var body: some View {\n \n if theme1 {\n CustomView(theme: $theme1)\n }\n else {\n CustomView(theme: $theme1)\n }\n \n }\n}\n
\nstruct CustomView: View {\n \n @Binding var theme1: Bool\n \n init(theme: Binding<Bool>) {\n \n _theme1 = theme\n \n let navBarAppearance = UINavigationBarAppearance()\n navBarAppearance.titleTextAttributes = [.foregroundColor: theme1 ? UIColor.red : UIColor.yellow]\n navBarAppearance.largeTitleTextAttributes = [.foregroundColor: theme1 ? UIColor.red : UIColor.yellow]\n navBarAppearance.backgroundColor = theme1 ? UIColor.yellow : UIColor.red\n UINavigationBar.appearance().standardAppearance = navBarAppearance\n UINavigationBar.appearance().compactAppearance = navBarAppearance\n UINavigationBar.appearance().scrollEdgeAppearance = navBarAppearance\n UINavigationBar.appearance().tintColor = theme1 ? UIColor.red : UIColor.yellow\n }\n \n var body: some View {\n NavigationView {\n VStack {\n Button("Toggle Style") {\n theme1.toggle()\n }\n .padding(8)\n .foregroundColor(theme1 ? Color(.red): Color(.yellow))\n .background(RoundedRectangle(cornerRadius: 10)\n .fill(theme1 ? Color(.yellow) : Color(.red)))\n }\n .navigationTitle("Theme Picker")\n }\n }\n \n}\n
\nVersion 2:
\nThis is a way that I would recommend: With this in mind that we should be responsible for navigationTitle ourself, like when it should be shown or hide or be small . . .
\nimport SwiftUI\n\nstruct ContentView: View {\n \n @State private var theme1 = true\n \n var body: some View {\n \n NavigationView {\n \n ZStack {\n \n theme1 ? Color.yellow.ignoresSafeArea() : Color.red.ignoresSafeArea()\n \n Color.white.cornerRadius(20).padding()\n \n VStack {\n \n Button(action: { theme1.toggle() }, label: {\n Text("Toggle Style")\n .bold()\n .padding(8)\n .background(theme1 ? Color.yellow : Color.red)\n .cornerRadius(10)\n })\n \n }\n \n }\n \n }\n .overlay(navigationTitle, alignment: .topLeading)\n .foregroundColor(theme1 ? Color.red : Color.yellow)\n .accentColor(theme1 ? Color.red : Color.yellow)\n \n }\n \n var navigationTitle: some View {\n \n return Text("Theme Picker").font(Font.largeTitle.bold()).padding().offset(y: 30)\n }\n\n}\n
\n","author":{"@type":"Person","name":"swiftPunk"},"upvoteCount":1}}}Reputation: 1005
I need to be able to change the colors in a SwiftUI View on demand. This is not an issue for switching colors on demand for objects in a View, but how would one be able to do that for the NavigationBar appearance properties? Here is how I set the Navigation Bar appearance when the view is initialized. Tapping the button changes the button colors, but not the Nav Bar appearance. Restarting the app with a different value for theme1 will show the correct colors, but tapping the button only changes the button colors and not the NavBar appearance.
struct ContentView: View {
@State private var theme1 = true
init() {
let navBarAppearance = UINavigationBarAppearance()
navBarAppearance.titleTextAttributes = [.foregroundColor: theme1 ? UIColor.red : UIColor.yellow]
navBarAppearance.largeTitleTextAttributes = [.foregroundColor: theme1 ? UIColor.red : UIColor.yellow]
navBarAppearance.backgroundColor = theme1 ? UIColor.yellow : UIColor.red
UINavigationBar.appearance().standardAppearance = navBarAppearance
UINavigationBar.appearance().compactAppearance = navBarAppearance
UINavigationBar.appearance().scrollEdgeAppearance = navBarAppearance
UINavigationBar.appearance().tintColor = theme1 ? UIColor.red : UIColor.yellow
}
var body: some View {
NavigationView {
VStack {
Button("Toggle Style") {
theme1.toggle()
}
.padding(8)
.foregroundColor(theme1 ? Color(.red): Color(.yellow))
.background(RoundedRectangle(cornerRadius: 10)
.fill(theme1 ? Color(.yellow) : Color(.red)))
}
.navigationTitle("Theme Picker")
}
}
}
Upvotes: 1
Views: 1392
Reputation: 1
Because we are using UIKit in code, we have to kill View First then create the one we want:
Version 1:
import SwiftUI
struct ContentView: View {
@State private var theme1 = true
var body: some View {
if theme1 {
CustomView(theme: $theme1)
}
else {
CustomView(theme: $theme1)
}
}
}
struct CustomView: View {
@Binding var theme1: Bool
init(theme: Binding<Bool>) {
_theme1 = theme
let navBarAppearance = UINavigationBarAppearance()
navBarAppearance.titleTextAttributes = [.foregroundColor: theme1 ? UIColor.red : UIColor.yellow]
navBarAppearance.largeTitleTextAttributes = [.foregroundColor: theme1 ? UIColor.red : UIColor.yellow]
navBarAppearance.backgroundColor = theme1 ? UIColor.yellow : UIColor.red
UINavigationBar.appearance().standardAppearance = navBarAppearance
UINavigationBar.appearance().compactAppearance = navBarAppearance
UINavigationBar.appearance().scrollEdgeAppearance = navBarAppearance
UINavigationBar.appearance().tintColor = theme1 ? UIColor.red : UIColor.yellow
}
var body: some View {
NavigationView {
VStack {
Button("Toggle Style") {
theme1.toggle()
}
.padding(8)
.foregroundColor(theme1 ? Color(.red): Color(.yellow))
.background(RoundedRectangle(cornerRadius: 10)
.fill(theme1 ? Color(.yellow) : Color(.red)))
}
.navigationTitle("Theme Picker")
}
}
}
Version 2:
This is a way that I would recommend: With this in mind that we should be responsible for navigationTitle ourself, like when it should be shown or hide or be small . . .
import SwiftUI
struct ContentView: View {
@State private var theme1 = true
var body: some View {
NavigationView {
ZStack {
theme1 ? Color.yellow.ignoresSafeArea() : Color.red.ignoresSafeArea()
Color.white.cornerRadius(20).padding()
VStack {
Button(action: { theme1.toggle() }, label: {
Text("Toggle Style")
.bold()
.padding(8)
.background(theme1 ? Color.yellow : Color.red)
.cornerRadius(10)
})
}
}
}
.overlay(navigationTitle, alignment: .topLeading)
.foregroundColor(theme1 ? Color.red : Color.yellow)
.accentColor(theme1 ? Color.red : Color.yellow)
}
var navigationTitle: some View {
return Text("Theme Picker").font(Font.largeTitle.bold()).padding().offset(y: 30)
}
}
Upvotes: 1