swift - 在 SwiftUI 中动态更改和更新导航栏的颜色

标签 swift swiftui uinavigationbar swiftui-navigationview uinavigationbarappearance

我正在尝试更改 SwiftUI 中的 NavigationBar 背景颜色,这是我使用以下代码完成的。但是,我还没有弄清楚如何动态更改和更新导航栏的背景颜色。

struct ContentView: View {
    @State var color: Color = .red
    
    init() {
        let navbarAppearance = UINavigationBarAppearance()
        navbarAppearance.largeTitleTextAttributes = [.foregroundColor: UIColor.white]
        navbarAppearance.titleTextAttributes = [.foregroundColor: UIColor.white]
        navbarAppearance.backgroundColor = UIColor(color)
        UINavigationBar.appearance().standardAppearance = navbarAppearance
        UINavigationBar.appearance().compactAppearance = navbarAppearance
        UINavigationBar.appearance().scrollEdgeAppearance = navbarAppearance
        
    }
    
    var body: some View {
        NavigationView {
                VStack(spacing: 20) {
                    Button(action: { color = .blue }) {
                        Text("Blue")
                            .font(.title)
                            .bold()
                            .foregroundColor(.white)
                            .frame(width: 100)
                            .padding()
                            .background(Color.blue)
                            .cornerRadius(15)
                    }
                    Button(action: { color = .red }) {
                        Text("Red")
                            .font(.title)
                            .bold()
                            .foregroundColor(.white)
                            .frame(width: 100)
                            .padding()
                            .background(Color.red)
                            .cornerRadius(15)
                    }
                }
                .offset(y: -50)
                .navigationTitle("My Navigation")
        }
    }
    
}

enter image description here 这段代码给出了正确的结果,但是点击其中一个按钮来更改 Color 变量不会更新 NavigationBar 的颜色。这是因为在初始化时,导航栏保留了它的所有特性,所以我需要找到一种方法来改变这些,如果可能的话,在改变颜色之间制作这种过渡动画。感谢您的帮助!

最佳答案

您可以使用 SwiftUI-Introspect ,所以您只是更改此 NavigationView 的导航栏。它不会影响任何其他实例。

您也不会使用 .id(...),这可能很糟糕,因为当 View 更改身份时,它可能会破坏动画、不必要地重新初始化 View 、破坏 View 生命周期等。

在我的示例中,您保存了 UINavigationController 的当前实例。当 color 的值改变时,导航栏的外观会重新设置。

内省(introspection)示例:

import Introspect

/* ... */

struct ContentView: View {
    @State private var color: Color = .red
    @State private var nav: UINavigationController?

    var body: some View {
        NavigationView {
            VStack(spacing: 20) {
                Button(action: { color = .blue }) {
                    Text("Blue")
                        .font(.title)
                        .bold()
                        .foregroundColor(.white)
                        .frame(width: 100)
                        .padding()
                        .background(Color.blue)
                        .cornerRadius(15)
                }

                Button(action: { color = .red }) {
                    Text("Red")
                        .font(.title)
                        .bold()
                        .foregroundColor(.white)
                        .frame(width: 100)
                        .padding()
                        .background(Color.red)
                        .cornerRadius(15)
                }
            }
            .offset(y: -50)
            .navigationTitle("My Navigation")
        }
        .introspectNavigationController { nav in
            self.nav = nav
            updateNavBar()
        }
        .onChange(of: color) { _ in
            updateNavBar()
        }
    }

    private func updateNavBar() {
        guard let nav = nav else { return }
        let navbarAppearance = UINavigationBarAppearance()
        navbarAppearance.largeTitleTextAttributes = [.foregroundColor: UIColor.white]
        navbarAppearance.titleTextAttributes = [.foregroundColor: UIColor.white]
        navbarAppearance.backgroundColor = UIColor(color)
        nav.navigationBar.standardAppearance = navbarAppearance
        nav.navigationBar.compactAppearance = navbarAppearance
        nav.navigationBar.scrollEdgeAppearance = navbarAppearance
    }
}

结果:

Result

关于swift - 在 SwiftUI 中动态更改和更新导航栏的颜色,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69262266/

相关文章:

swift - 切换大小写以检查 ViewController 是否符合协议(protocol)

SwiftUI:onDelete 无法正确更新 UI

swift - NavigationView + GeometryReader View 返回不正确的大小

ios - 透明导航栏(swift 3)

快速进度 View 完成操作

swift - 检测 SKNode 和粒子之间的碰撞?

animation - 如何在 SwiftUI 中停止动画 ().repeatForever

ios7 - 导航栏下方的空白区域,且 displayedSearchBarInNavigationBar = YES

ios - 导航栏按钮 Action 调用失败

ios - 在 Swift 中对 Firebase 实时数据库数据进行排序