【问题标题】:Switching UINavigationBar Appearance in SwiftUI在 SwiftUI 中切换 UINavigationBar 外观
【发布时间】:2021-06-23 22:12:16
【问题描述】:

我需要能够按需更改 SwiftUI 视图中的颜色。这不是根据需要为视图中的对象切换颜色的问题,但是如何为 NavigationBar 外观属性做到这一点?这是我在视图初始化时设置导航栏外观的方法。点击按钮会更改按钮颜色,但不会更改导航栏的外观。使用不同的 theme1 值重新启动应用程序将显示正确的颜色,但点击按钮只会更改按钮颜色,而不会更改 NavBar 的外观。

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")
    }
}

}

【问题讨论】:

    标签: swiftui themes uinavigationbarappearance


    【解决方案1】:

    因为我们在代码中使用 UIKit,所以我们必须先杀死 View,然后创建我们想要的:


    版本 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")
            }
        }
        
    }
    

    版本 2:

    这是我推荐的一种方式:考虑到这一点,我们应该对 navigationTitle 自己负责,比如何时应该显示、隐藏或变小。 . .


    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)
        }
    
    }
    

    【讨论】:

    • 谢谢。我实际上更喜欢第一种方式,尽管它仍然不理想。非常感谢您抽出宝贵时间做出如此详细的回复。
    • @StewartLynch: 绝对欢迎你,我只是推荐第二种方式,因为纯 SwiftUI,我也是你的教学风格的忠实粉丝,我总是向任何要求一个好地方的人推荐你的 youtube 频道学习 Swift/SwiftUI,谢谢你的辛勤工作!
    • 感谢您的评论。事实上,我正在整理一个关于在 SwiftUI 中为应用程序主题化的教程,所以这是缺少的部分之一。当我制作视频时,如果您觉得可以,我想将这个解决方案归功于您,因为我将使用它。如果你让我知道你的推特账号,我会确保你在视频中得到认可。
    • @StewartLynch:你太棒了,很喜欢看今天关于 Package 的视频,我没有 Swift 编程相关的 Twitter,我只是一个有趣的程序员。无论您是否谈论我,这都是您的决定,我通过 StackOverFlow 分享的任何内容都没有版权或某些内容,但就我个人而言,我很高兴从我的老师那里听到我的名字。如果您认为它可以使该视频更好地做到这一点,否则我也可以不提。
    • @StewartLynch:我刚刚在这里用同样的方式回答了另一个问题:stackoverflow.com/a/67096930/14998134
    猜你喜欢
    • 1970-01-01
    • 2014-03-06
    • 2020-03-13
    • 2017-07-05
    • 1970-01-01
    • 1970-01-01
    • 2023-04-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多