如何在Swiftui中动态改变UINavigationBar的颜色



我在SwiftUI工作,我试图让导航栏更新它的颜色当一个按钮被按下。

我看到有相关的问题,但它只允许在导航视图中使用静态颜色。

在提供的示例中,我只看到了当选项卡在按下按钮后发生变化时工具栏发生变化。

是否有一种方法可以在不改变选项卡的情况下更新视图(我认为这需要创建一个新的navigationView)

struct ContentView: View {
var body: some View {
TabView {
First()
.tabItem{
Image(systemName: "1.square")
}
Second()
.tabItem{
Image(systemName: "2.square")
}
Third()
.tabItem{
Image(systemName: "3.square")
}
}
}//:Body
}//:ContentView


struct First: View {


var body: some View {
NavigationView {
HStack {
Button(action: {
let appearance = UINavigationBarAppearance()
appearance.backgroundColor = UIColor(.red)
UINavigationBar.appearance().barTintColor = UIColor(.red)
UINavigationBar.appearance().standardAppearance = appearance
UINavigationBar.appearance().compactAppearance = appearance
UINavigationBar.appearance().scrollEdgeAppearance = appearance
}, label: {
Text("red")
})//:Button
Button(action: {
let appearance = UINavigationBarAppearance()
appearance.backgroundColor = UIColor(.blue)
UINavigationBar.appearance().barTintColor = UIColor(.blue)
UINavigationBar.appearance().standardAppearance = appearance
UINavigationBar.appearance().compactAppearance = appearance
UINavigationBar.appearance().scrollEdgeAppearance = appearance
}, label: {
Text("blue")
})//:Button
}

.toolbar(content: {
ToolbarItem(placement: .principal, content: {
Text("Hello World 1")
})
})
}//:NavView
}

}


struct Second: View {
var body: some View {
NavigationView {
ScrollView {
Text("Don't use .appearance()!")
}
.navigationBarTitle("Try it!", displayMode: .inline)
.background(NavigationConfigurator { nc in
nc.navigationBar.barTintColor = .green
nc.navigationBar.titleTextAttributes = [.foregroundColor : UIColor.white]
})
}
.navigationViewStyle(StackNavigationViewStyle())
}
}


struct NavigationConfigurator: UIViewControllerRepresentable {
var configure: (UINavigationController) -> Void = { _ in }
func makeUIViewController(context: UIViewControllerRepresentableContext<NavigationConfigurator>) -> UIViewController {
UIViewController()
}
func updateUIViewController(_ uiViewController: UIViewController, context: UIViewControllerRepresentableContext<NavigationConfigurator>) {
if let nc = uiViewController.navigationController {
self.configure(nc)
}
}
}

struct Third: View {
@State var navigationBackground: UIColor = UIColor(.gray)

var body: some View {
NavigationView {
HStack {
Spacer()

Button(action: {
navigationBackground = UIColor(.purple)
}, label: {
Text("purple")
.foregroundColor(.purple)
})//:Button

Spacer()

Button(action: {
navigationBackground = UIColor(.black)
}, label: {
Text("black")
.foregroundColor(.black)
})//:Button

Spacer()
}

.toolbar(content: {
ToolbarItem(placement: .principal, content: {
Text("Hello World 1")
})
})

}//:NavView
.navigationBarColor(backgroundColor: navigationBackground, titleColor: UIColor(.red))
.navigationBarTitleDisplayMode(.inline)
}
}

struct NavigationBarModifier: ViewModifier {
var backgroundColor: UIColor?
var titleColor: UIColor?
init(backgroundColor: UIColor?, titleColor: UIColor?) {
self.backgroundColor = backgroundColor
let coloredAppearance = UINavigationBarAppearance()
coloredAppearance.configureWithTransparentBackground()
coloredAppearance.backgroundColor = backgroundColor
coloredAppearance.titleTextAttributes = [.foregroundColor: titleColor ?? .white]
coloredAppearance.largeTitleTextAttributes = [.foregroundColor: titleColor ?? .white]
UINavigationBar.appearance().standardAppearance = coloredAppearance
UINavigationBar.appearance().compactAppearance = coloredAppearance
UINavigationBar.appearance().scrollEdgeAppearance = coloredAppearance

UIToolbar.appearance().barTintColor = backgroundColor
}
func body(content: Content) -> some View {
ZStack{
content
VStack {
GeometryReader { geometry in
Color(self.backgroundColor ?? .clear)
.frame(height: geometry.safeAreaInsets.top)
.edgesIgnoringSafeArea(.top)
Spacer()
}
}
}
}
}
extension View {
func navigationBarColor(backgroundColor: UIColor?, titleColor: UIColor?) -> some View {
self.modifier(NavigationBarModifier(backgroundColor: backgroundColor, titleColor: titleColor))
}
}

我尝试的解决方案是这个帖子的答案的衍生:SwiftUI更新导航栏标题颜色

我只是在这里找到了一个解决方案SwiftUI:更新导航条颜色

在导航视图上的id属性似乎可以使一切工作强制更改。

这对我的用例有效。

最新更新