【问题标题】:SwiftUI update navigation bar title colorSwiftUI 更新导航栏标题颜色
【发布时间】:2019-10-23 14:56:41
【问题描述】:

如何在 SwiftUI 中更改导航栏标题颜色

NavigationView {
            List{
                ForEach(0..<15) { item in
                    HStack {
                        Text("Apple")
                            .font(.headline)
                            .fontWeight(.medium)
                            .color(.orange)
                            .lineLimit(1)
                            .multilineTextAlignment(.center)
                            .padding(.leading)
                            .frame(width: 125, height: nil)


                        Text("Apple Infinite Loop. Address: One Infinite Loop Cupertino, CA 95014 (408) 606-5775 ")
                            .font(.subheadline)
                            .fontWeight(.regular)
                            .multilineTextAlignment(.leading)
                            .lineLimit(nil)


                    }
                }
            }
            .navigationBarTitle(Text("TEST")).navigationBarHidden(false).foregroundColor(.orange)
            }

我尝试过.foregroundColor(.orange),但它不起作用

也试过.navigationBarTitle(Text("TEST").color(.orange))

有什么帮助吗?

【问题讨论】:

  • 嗯..似乎swiftUI忽略了为导航栏标题设置的任何修饰符......而且我们不能在导航栏中放置任何视图也很奇怪:-(

标签: ios navigationbar swiftui


【解决方案1】:

不需要在全局范围内使用.appearance()

虽然 SwiftUI 不直接公开导航样式,但您可以使用 UIViewControllerRepresentable 解决这个问题。由于 SwiftUI 在后台使用常规的UINavigationController,因此视图控制器仍然具有有效的.navigationController 属性。

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 ContentView: View {
    var body: some View {
        NavigationView {
            ScrollView {
                Text("Don't use .appearance()!")
            }
            .navigationBarTitle("Try it!", displayMode: .inline)
            .background(NavigationConfigurator { nc in
                nc.navigationBar.barTintColor = .blue
                nc.navigationBar.titleTextAttributes = [.foregroundColor : UIColor.white]
            })
        }
    .navigationViewStyle(StackNavigationViewStyle())
    }
}

【讨论】:

  • 不适用于子视图,即使您在所述子视图中声明.background,导航栏也会保持相同的颜色。
  • 嗯,如果这是在场景委托中设置的初始视图,它似乎第一次不起作用; vc.navigationController 在闭包中为零。当我从某个地方展示一个 VC 时,它会立即以适当的样式重新加载...
  • 很遗憾不能使用 large 显示模式
  • filipmolcik.com/… 中所述,使用 viewModifier 代替 UIViewControllerRepresentable 解决了许多此类问题,例如滚动视图重叠、首次加载时颜色不生效、半透明效果和间歇性性能问题。
  • 最新的解决方案,我得到了vc.navigationController nil,就像另一个一样,我完美地复制了所有代码以确保没有错,但仍然是navbar title colornavbar bar tint color 不会改变.. 然后@gyleg5 回答解决了我的问题。 this source
【解决方案2】:

在 SwiftUI 中,您不能直接更改 navigationTitleColor。您必须像这样更改 UINavigation 在init() 中的外观,

struct YourView: View {

    init() {
        //Use this if NavigationBarTitle is with Large Font
        UINavigationBar.appearance().largeTitleTextAttributes = [.foregroundColor: UIColor.red]

        //Use this if NavigationBarTitle is with displayMode = .inline
        UINavigationBar.appearance().titleTextAttributes = [.foregroundColor: UIColor.red]
    }

    var body: some View {

        NavigationView {
            List{
                ForEach(0..<15) { item in
                    HStack {
                        Text("Apple")
                            .font(.headline)
                            .fontWeight(.medium)
                            .color(.orange)
                            .lineLimit(1)
                            .multilineTextAlignment(.center)
                            .padding(.leading)
                            .frame(width: 125, height: nil)


                        Text("Apple Infinite Loop. Address: One Infinite Loop Cupertino, CA 95014 (408) 606-5775 ")
                            .font(.subheadline)
                            .fontWeight(.regular)
                            .multilineTextAlignment(.leading)
                            .lineLimit(nil)
                    }
                }
            }
            .navigationBarTitle(Text("TEST")).navigationBarHidden(false)
            //.navigationBarTitle (Text("TEST"), displayMode: .inline)
        }
    }
}

我希望它会起作用。谢谢!!

【讨论】:

  • 你知道如何在 WatchOS 上使用 SwiftUI 做到这一点吗?
  • 我收到一个错误:Use of unresolved identifier 'UINavigationBar'
  • NavigationView 在 watchOS 中不可用。
  • 检查你的帖子stackoverflow.com/questions/58035341/…,我在那里回答了你如何改变它。
  • 这在全球范围内有效,并将影响应用程序中的所有其他视图。
【解决方案3】:

在 iOS 14 中,SwiftUI 可以使用新的 toolbar 修饰符自定义导航栏。

我们需要将放置类型.principalToolbarItem 设置为新的toolbar 修饰符。您甚至可以设置图像等等。

NavigationView {
    Text("My View!")
        .navigationBarTitleDisplayMode(.inline)
        .toolbar {
            ToolbarItem(placement: .principal) {
                HStack {
                    Image(systemName: "sun.min.fill")
                    Text("Title")
                        .font(.headline)
                        .foregroundColor(.orange)
                }
            }
        }
}

【讨论】:

  • 但是你不能设置工具栏的背景颜色,对吧?
  • 这仅适用于 displayMode .inline,正如您在此处所拥有的,但不适用于 .large
  • 这不能回答问题。
【解决方案4】:

我搜索了这个问题并找到了一篇很棒的文章,您可以将导航栏样式的设置包装为视图修饰符。

检查这个Link

注意:我相信你需要更新这个例子中的一些代码,添加titleColor参数。

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
    }

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

}

之后,像这样申请:

.navigationBarColor(backgroundColor: .clear, titleColor: .white)

我希望它会起作用。

【讨论】:

  • 感谢您的解决方案 :) 效果惊人!但是当导航栏标题切换到内联外观时,栏的高度仍然没有减少?您是否尝试过任何解决方法?在此先感谢:D
  • 这应该是公认的答案。使用 UIViewControllerRepresentable 会导致很多问题,例如重叠滚动视图,有时根本不改变颜色。
  • 这太棒了!原始文章应该有coloredAppearance.backgroundColor = backgroundColor 而不是coloredAppearance.backgroundColor = .clear,就像你所做的那样——因为橡皮筋滚动效果。
  • 这个解决方案非常适合修改全局导航栏。使用此解决方案导航到子视图时,是否有人能够更改样式?
  • 如果用户在使用您的应用程序时在明暗模式之间切换,条形颜色不会随之改变。我建议将另一个参数添加到名为style 的修饰符,类型为UIUserInterfaceStyle,并为UITraitCollectioninit(userInterfaceStyle:) 分配外观。这样,如果用户在使用您的应用程序时在明暗模式之间切换,导航栏颜色也会发生变化。不过,每种样式都需要一个修饰符
【解决方案5】:

根据 Arsenius 的回答,我发现让它持续工作的一种优雅方法是继承 UIViewController 并在 viewDidLayoutSubviews() 中进行配置。

用法:

VStack {
    Text("Hello world")
        .configureNavigationBar {
            $0.navigationBar.setBackgroundImage(UIImage(), for: .default)
            $0.navigationBar.shadowImage = UIImage()
        }
}

实施:

extension View {
    func configureNavigationBar(configure: @escaping (UINavigationController) -> Void) -> some View {
        modifier(NavigationConfigurationViewModifier(configure: configure))
    }
}

struct NavigationConfigurationViewModifier: ViewModifier {
    let configure: (UINavigationController) -> Void

    func body(content: Content) -> some View {
        content.background(NavigationConfigurator(configure: configure))
    }
}

struct NavigationConfigurator: UIViewControllerRepresentable {
    let configure: (UINavigationController) -> Void

    func makeUIViewController(
        context: UIViewControllerRepresentableContext<NavigationConfigurator>
    ) -> NavigationConfigurationViewController {
        NavigationConfigurationViewController(configure: configure)
    }

    func updateUIViewController(
        _ uiViewController: NavigationConfigurationViewController,
        context: UIViewControllerRepresentableContext<NavigationConfigurator>
    ) { }
}

final class NavigationConfigurationViewController: UIViewController {
    let configure: (UINavigationController) -> Void

    init(configure: @escaping (UINavigationController) -> Void) {
        self.configure = configure
        super.init(nibName: nil, bundle: nil)
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()

        if let navigationController = navigationController {
            configure(navigationController)
        }
    }
}

【讨论】:

  • 这确实解决了导航控制器在第一次加载时为零时的问题。谢谢!
  • 这肯定工作得更好。在 iOS 14 上测试
  • 很高兴我能帮上忙!!
  • 有什么方法可以让.navigationBarTitleDisplayMode(.automatic) 工作?它似乎只适用于 .large.inline - 设置为自动时从不会从大转换到内联。
  • 显然,从 XCode 13 开始,viewDidLayoutSubviews 不起作用,但 viewWillAppear 在 iOS 14 上起作用?‍♂️
【解决方案6】:

我采取了稍微不同的方法;我只想更改标题文本颜色,而没有其他关于NavigationBar 的内容。使用上述和this 作为灵感,我登陆了:

import SwiftUI

extension View {
    /// Sets the text color for a navigation bar title.
    /// - Parameter color: Color the title should be
    ///
    /// Supports both regular and large titles.
    @available(iOS 14, *)
    func navigationBarTitleTextColor(_ color: Color) -> some View {
        let uiColor = UIColor(color)
    
        // Set appearance for both normal and large sizes.
        UINavigationBar.appearance().titleTextAttributes = [.foregroundColor: uiColor ]
        UINavigationBar.appearance().largeTitleTextAttributes = [.foregroundColor: uiColor ]
    
        return self
    }
}

这需要 iOS 14,因为 UIColor.init(_ color: Color) 需要 iOS 14。

可以这样利用:

struct ExampleView: View {
    var body: some View {
        NavigationView {
            Text("Hello, World!")
                .navigationBarTitle("Example")
                .navigationBarTitleTextColor(Color.red)
        }
    }
}

这反过来产生:

【讨论】:

  • 你能说我应该在哪里调用这个函数吗?它给了我错误“在范围内找不到'自我'”
【解决方案7】:

我开发了一个自定义 SwiftUI 导航的小示例,它可以提供完整的可视化自定义和程序化导航。它可以用作 NavigationView 的替代品。

这是处理 currentView 和导航堆栈的 NavigationStack 类:

final class NavigationStack: ObservableObject  {
    @Published var viewStack: [NavigationItem] = []
    @Published var currentView: NavigationItem

    init(_ currentView: NavigationItem ){
        self.currentView = currentView
    }

    func unwind(){
        if viewStack.count == 0{
            return
        }

        let last = viewStack.count - 1
        currentView = viewStack[last]
        viewStack.remove(at: last)
    }

    func advance(_ view:NavigationItem){
        viewStack.append( currentView)
        currentView = view
    }

    func home( ){
        currentView = NavigationItem( view: AnyView(HomeView()))
        viewStack.removeAll()
    }
}

您可以查看here: 以获取完整示例和说明:

PS:我不知道为什么这个被删除了。我认为它回答了这个问题,因为它是 NavigationView 的完美功能替代品。

【讨论】:

    【解决方案8】:

    在 SwiftUI 中使用以下代码自定义颜色

    这是主体背景颜色:-

    struct ContentView: View {
    
    var body: some View {
    
     Color.red
    .edgesIgnoringSafeArea(.all)
    
     }
    
    }
    

    对于导航栏:-

    struct ContentView: View {
    
    @State var msg = "Hello SwiftUI?"
    
    init() {
    
        UINavigationBar.appearance().backgroundColor = .systemPink
    
         UINavigationBar.appearance().largeTitleTextAttributes = [
            .foregroundColor: UIColor.white,
                   .font : UIFont(name:"Helvetica Neue", size: 40)!]
    
    }
    
    var body: some View {
    
        NavigationView {
    
        Text(msg)
    
            .navigationBarTitle(Text("NAVIGATION BAR"))
    
        }
    
        }
    
      }
    

    对于其他 UI 元素颜色自定义

    struct ContentView: View {
    
    @State var msg = "Hello SwiftUI?"
    
    var body: some View {
    
            Text(msg).padding()
                .foregroundColor(.white)
                .background(Color.pink)
    
        }
     }
    

    【讨论】:

    • tks,设置 largeTitleTextAttributes 对我有用
    【解决方案9】:
    init() {
        // for navigation bar title color
        UINavigationBar.appearance().titleTextAttributes = [NSAttributedString.Key.foregroundColor:UIColor.red]
       // For navigation bar background color 
        UINavigationBar.appearance().backgroundColor = .green
    }
    
    NavigationView {
           List {
               ForEach(0..<15) { item in
                   HStack {
                        Text("Apple")
                           .font(.headline)
                           .fontWeight(.medium)
                           .color(.orange)
                           .lineLimit(1)
                           .multilineTextAlignment(.center)
                           .padding(.leading)
                           .frame(width: 125, height: nil)
    
                        Text("Apple Infinite Loop. Address: One Infinite Loop Cupertino, CA 95014 (408) 606-5775 ")
                           .font(.subheadline)
                           .fontWeight(.regular)
                           .multilineTextAlignment(.leading)
                           .lineLimit(nil)
                    }
               }
           }
           .navigationBarTitle(Text("TEST")).navigationBarHidden(false)
    }
    

    【讨论】:

    • 谢谢,我知道外观 api 可以做到(见我的 cmets)我需要 swift ui 版本的解决方案
    • 如果视图以模态方式呈现,似乎不起作用。
    • @MycroftCanner 那是因为模态不继承根导航视图。
    • @kdion4891 但我在模态视图的顶部实现了 NavigationView {}
    【解决方案10】:

    如果你的内容是

    struct MyContent : View {
    ...
    }
    

    然后你可以把它放在一个带有红色背景的导航视图中:

    NavigationView {
        ZStack(alignment: .top) {
            Rectangle()
                .foregroundColor(Color.red)
                .edgesIgnoringSafeArea(.top)
            MyContent()
        }
    }
    

    我会在知道如何更新标题文本后立即更新我的答案。

    【讨论】:

      【解决方案11】:

      您可以使用SwiftUI-Introspect 单独设置它们,而不是设置影响所有导航栏的appearance()

      例子:

      struct ContentView: View {
          var body: some View {
              NavigationView {
                  ScrollView {
                      Text("Hello world!")
                  }
                  .navigationTitle("Title")
              }
              .introspectNavigationController { nav in
                  nav.navigationBar.barTintColor = .systemBlue
              }
          }
      }
      

      结果:

      【讨论】:

      • 这实际上是一个很好的建议,谢谢!我花了几天时间寻找一种方便的方法来自定义 NavigationView 标题,并且效果很好?
      【解决方案12】:

      肯定已经有一些很好的答案,但它们都只涵盖了部分工作:

      1. 来自@arsenius 的出色解决方案 - 给出一个好的开始

      2. 来自@EngageTheWarpDrive 的优雅方式 - 这绝对提高了可用性

      3. 对于最新版本的iOS和swiftUI@Thahir建议使用工具栏

      很少有其他建议建议使用UIAppearence 全局配置UINavigationBar - 对我而言,全局更改不是一个好主意,可能并不总是合适。

      我最终将所有提案合并到下一个代码中:

      1. navigationBar 配置创建NavigationControllerRepresentablemodifier

         struct NavigationControllerLayout: UIViewControllerRepresentable {
        
             var configure: (UINavigationController) -> () = { _ in }
        
             func makeUIViewController(
                 context: UIViewControllerRepresentableContext<NavigationControllerLayout>
             ) -> UIViewController {
                 UIViewController()
             }
        
             func updateUIViewController(
                 _ uiViewController: UIViewController,
                 context: UIViewControllerRepresentableContext<NavigationControllerLayout>
             ) {
                 if let navigationContoller = uiViewController.navigationController {
                     configure(navigationContoller)
                 }
             }
         }
        
         extension View {
        
             func configureNavigationBar(_ configure: @escaping (UINavigationBar) -> ()) -> some View {
                 modifier(NavigationConfigurationViewModifier(configure: configure))
             }
         }
        
         struct NavigationConfigurationViewModifier: ViewModifier {
        
             let configure: (UINavigationBar) -> ()
        
             func body(content: Content) -> some View {
                 content.background(NavigationControllerLayout(configure: {
                     configure($0.navigationBar)
                 }))
             }
         }
        
      2. 修改navigationBar以满足您的要求(例如背景颜色和其他道具):

        extension UINavigationBar {
        
             enum Appearence {
        
                 case transparent
                 case defaultLight
                 case colored(UIColor?)
        
                 var color: UIColor {
                     ...
                 }
        
                 var appearenceColor: UIColor {
                     ...
                 }
        
                 var tint: UIColor {
                     ....
                 }
        
                 var effect: UIBlurEffect? {
                    ....
                 }
             }
        
             func switchToAppearence(_ type: Appearence) {
                 backgroundColor = type.color
                 barTintColor = type.tint
        
                 // for iOS 13+
                 standardAppearance.backgroundColor = type.appearenceColor
                 standardAppearance.backgroundEffect = type.effect
        
                 // u can use other properties from navBar also simply modifying this function
             }
         }
        
      3. 如您所见,这里我们肯定需要在ColorUIColor 之间建立一些桥梁。从iOS 14 开始 - 你可以只是UIColor.init(_ color: Color),但在iOS 14 之前没有这样的方法,所以我最终得到了简单的解决方案:

         extension Color {
        
             /// Returns a `UIColor` that represents this color if one can be constructed
             ///
             /// Note: Does not support dynamic colors
             var uiColor: UIColor? {
                 self.cgColor.map({ UIColor(cgColor: $0) })
             }
         }
        

      这不适用于动态颜色

      1. 结果你可以使用如下:

         // modifier to `NavigationView`
         .configureNavigationBar {
             $0.switchToAppearence(.defaultLight)
         }
        

      希望这可能对某人有所帮助;)

      【讨论】:

        【解决方案13】:

        这是对我有用的解决方案。您需要从 UINavigationController 作为 rootViewController 开始。

        func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
            if let windowScene = scene as? UIWindowScene {
                let window = UIWindow(windowScene: windowScene)
                let nav = setupNavigationController()
                window.rootViewController = nav
                self.window = window
                window.makeKeyAndVisible()
            }
        }
        
        func setupNavigationController() -> UINavigationController {
            let contentView = ContentView()
            let hosting = UIHostingController(rootView: contentView)
            let nav = NavigationController(rootViewController: hosting)
            let navBarAppearance = UINavigationBarAppearance()
            navBarAppearance.titleTextAttributes = [.foregroundColor: UIColor.white]
            navBarAppearance.largeTitleTextAttributes = [.foregroundColor: UIColor.white]
            navBarAppearance.backgroundColor = UIColor.black
            nav.navigationBar.standardAppearance = navBarAppearance
            nav.navigationBar.scrollEdgeAppearance = navBarAppearance
            nav.navigationBar.prefersLargeTitles = true
            return nav
        }
        

        然后在您的内容视图中:

        struct ContentView: View {
        
            @State private var isModalViewPresented: Bool = false
        
            var body: some View {
                List(0 ..< 10, rowContent: { (index) in
                    NavigationLink(destination: DetailView()) {
                        Text("\(index)")
                    }
                })
                .navigationBarItems(trailing: Button("Model") {
                    self.isModalViewPresented.toggle()
                })
                .sheet(isPresented: $isModalViewPresented, content: {
                    ModalView()
                })
                .navigationBarTitle("Main View")
            }
        }
        

        如果您想在某些时候更改颜色,例如在模态视图中,请使用给出的答案here

        struct ModalView: View {
            var body: some View {
                NavigationView {
                   Text("Hello, World!")
                   .navigationBarTitle("Modal View")
                   .background(NavigationConfigurator { nc in
                      nc.navigationBar.backgroundColor = UIColor.blue
                      nc.navigationBar.largeTitleTextAttributes = [.foregroundColor: UIColor.white]
                   })
               }
            }
        }
        

        你可以继承 UINavigationController 来改变状态栏的颜色

        class NavigationController: UINavigationController {
        
            override func viewDidLoad() {
                super.viewDidLoad()
            }
        
            override var preferredStatusBarStyle: UIStatusBarStyle 
            {
                .lightContent
            }
        }
        

        【讨论】:

          【解决方案14】:

          .foregroundColor(.orange) - изменяет внутренние представления NavigationView。

          但是要改变导航视图本身,需要在init()中使用UINavigationBar Appearance()

          我一直在寻找这个问题,并找到了一篇关于 it 的精彩文章。我通过这篇文章修改了你的代码并取得了成功。在这里,我如何解决这个问题:

          struct ContentView: View {
              
              init() {
                  let coloredAppearance = UINavigationBarAppearance()
                  
                  // this overrides everything you have set up earlier.
                  coloredAppearance.configureWithTransparentBackground()
                  coloredAppearance.backgroundColor = .green
                  coloredAppearance.largeTitleTextAttributes = [.foregroundColor: UIColor.black]
                  
                  // to make everything work normally
                  UINavigationBar.appearance().standardAppearance = coloredAppearance
                  UINavigationBar.appearance().scrollEdgeAppearance = coloredAppearance
              }
              
              var body: some View {
                  NavigationView {
                      List{
                          ForEach(0..<15) { item in
                              HStack {
                                  Text("Apple")
                                      .font(.headline)
                                      .fontWeight(.medium)
                                      .lineLimit(1)
                                      .multilineTextAlignment(.center)
                                      .padding(.leading)
                                      .frame(width: 125, height: nil)
                                      .foregroundColor(.orange)
                                  
                                  
                                  Text("Apple Infinite Loop. Address: One Infinite Loop Cupertino, CA 95014 (408) 606-5775 ")
                                      .font(.subheadline)
                                      .fontWeight(.regular)
                                      .multilineTextAlignment(.leading)
                                      .lineLimit(nil)
                                      .foregroundColor(.orange)
                              }
                          }
                      }
                      .navigationBarTitle(Text("TEST"))
                  }
          // do not forget to add this
                  .navigationViewStyle(StackNavigationViewStyle())
              }
          }
          

          你也可以举一些例子here

          【讨论】:

            【解决方案15】:

            我还没有弄清楚如何在每个视图的基础上设置前景色,但我确实想出了一个简单的背景色解决方法。

            如果使用.inline 标题,您可以只使用VStack,在NavigationView 的顶部有一个矩形:

            NavigationView {
                VStack() {
                    Rectangle()
                        .foregroundColor(.red)
                        .edgesIgnoringSafeArea(.top)
                        .frame(height: 0)
            
                    List {
                        Text("Hello World")
                        Text("Hello World")
                        Text("Hello World")
                    }
                }
                .navigationBarTitle("Hello World", displayMode: .inline)
                // ...
            

            注意矩形如何使用0.edgesIgnoringSafeArea(.top) 的框架高度。

            【讨论】:

              【解决方案16】:

              13.4 更新

              注意:第二天重新访问,我的一些问题可能是由于我的一些不标准的设置引起的:我仍在运行 mojave,但手动添加了 13.4 支持文件(通常只能通过xcode 11.4,需要 catalina)。我之所以提到这一点,是因为我 / 也有一些标签栏自定义颜色问题,但我只是注意到这些问题只有在我实际插入手机并从 xcode 运行应用程序时才会显现出来。如果我拔掉电源并正常运行应用程序,我没有看到标签栏问题,所以导航栏问题可能有一些相似之处......

              (我会将其添加为对上述 arsenius 答案(当前接受的答案)的评论,但我没有代表,所以...)

              我正在使用该解决方案,并且在 13.4 之前它一直运行良好,这似乎已经破坏了它,至少对我来说是这样。经过大量的视图层次跟踪,看起来他们改变了一些事情,使得隐式 UINavigationController 不再像解决方法中描述的那样通过传递的 UIViewController 轻松访问。它仍然在那里(离树很远),我们只需要找到它。

              为此,我们可以遍历视图层次结构,直到找到导航栏,然后像往常一样在其上设置所需的参数。这需要一个新的发现功能,以及 NavigationConfigurator 结构的一些小改动,以及它的实例化......

              首先,发现功能:

              func find_navbar(_ root: UIView?) -> UINavigationBar?
              {
                  guard root != nil else { return nil }
              
                  var navbar: UINavigationBar? = nil
                  for v in root!.subviews
                  {   if type(of: v) == UINavigationBar.self { navbar = (v as! UINavigationBar); break }
                      else { navbar = find_navbar(v); if navbar != nil { break } }
                  }
              
                  return navbar
              }
              

              如下修改 NavigationConfigurator(请注意,我们不再关心传入视图,因为这不再可靠):

              struct NavigationConfigurator: UIViewControllerRepresentable
              {
                  @EnvironmentObject var prefs: Prefs     // to pick up colorscheme changes
              
                  var configure: () -> Void = {}
                  func makeUIViewController(context: UIViewControllerRepresentableContext<NavigationConfigurator>) -> UIViewController { UIViewController() }
                  func updateUIViewController(_ uiViewController: UIViewController, context: UIViewControllerRepresentableContext<NavigationConfigurator>) { self.configure() }
              }
              

              (在我的应用程序中,我有一个 Prefs 对象来跟踪颜色等)

              ...然后,在实例化站点,执行以下操作:

              MyView()
                  .navigationBarTitle("List", displayMode: .inline)
                  .navigationBarItems(trailing: navbuttons)
                  .background(NavigationConfigurator {
                      if self.prefs.UI_COLORSCHEME != Colorscheme.system.rawValue
                      {   if let navbar = find_navbar(root_vc?.view)
                          {   navbar.barTintColor = Colors.uicolor(.navbar, .background)
                              navbar.backgroundColor = .black
                              navbar.titleTextAttributes = [.foregroundColor: Colors.uicolor(.navbar, .foreground)]
                              navbar.tintColor = Colors.uicolor(.navbar, .foreground)
                          }
                      }
                  })
              

              请注意,我在应用程序的其他位置捕获了根视图控制器,并在此处使用它传递给 find_navbar()。您可能想以不同的方式进行操作,但由于其他原因,我已经有了该变量...还有一些其他特定于我的应用程序的东西,例如与颜色相关的对象,但您明白了。

              【讨论】:

                【解决方案17】:

                https://stackoverflow.com/a/58427754/4709057 这个答案有效,但如果您遇到 navigationController 在明暗模式下为零的问题。只需添加这个.. 不知道为什么会起作用。

                struct ContentView: View {
                   var body: some View {
                      NavigationView {
                        ScrollView {
                            Text("Don't use .appearance()!")
                        }
                        .navigationBarTitle("Try it!", displayMode: .inline)
                        .background(NavigationConfigurator { nc in
                            nc.navigationBar.barTintColor = .blue
                            nc.navigationBar.background = .blue
                            nc.navigationBar.titleTextAttributes = [.foregroundColor : UIColor.white]
                        })
                    }
                   .navigationViewStyle(StackNavigationViewStyle())
                   .accentColor(.red)   <------- DOES THE JOB
                  }
                }
                

                【讨论】:

                  【解决方案18】:

                  使用 SwiftUI 的 WatchOS 导航标题颜色
                  watchOS 的旁注是您不需要摆弄导航颜色。这是您需要更改的 Watch Accent 颜色。在您的项目中进入 WatchProjectName->Asset->Accent 并更改它

                  https://developer.apple.com/documentation/watchkit/setting_the_app_s_tint_color

                  【讨论】:

                    【解决方案19】:

                    如果您不介意全局更改它,我发现进入资产目录并设置 AccentColor 是可行的。

                    【讨论】:

                      【解决方案20】:

                      对我有用的解决方案是使用 UINavigationBarAppearance() 方法,然后将 .id() 添加到 NavigationView。这将在颜色发生变化时自动重绘组件。

                      现在您可以根据状态引擎进行响应式颜色更改。

                      var body: some Scene {
                        let color = someValue ? UIColor.systemBlue : UIColor.systemGray3
                      
                        let custom = UINavigationBarAppearance()
                        custom.configureWithOpaqueBackground()
                        custom.backgroundColor = color
                        UINavigationBar.appearance().standardAppearance = custom
                        UINavigationBar.appearance().scrollEdgeAppearance = custom
                        UINavigationBar.appearance().compactAppearance = custom
                        UINavigationBar.appearance().compactScrollEdgeAppearance = custom
                      
                        return WindowGroup {
                          NavigationView {
                            content
                          }
                            .id(color.description)
                        }
                      }
                      

                      【讨论】:

                        【解决方案21】:

                        我找到的最简单的方法是:

                        init() {
                            UINavigationBar.appearance().tintColor = UIColor.systemBlue
                            }
                        

                        除了 systemBlue,你可以使用任何你想要的颜色。 您必须在“var body: some View {}”之外实现它。 您还可以添加:

                        @Environment(/.colorScheme) var colorScheme
                        

                        init() 之上,然后您可以使用 .dark 或 .light 在深色模式和浅色模式下按照您想要的方式更改颜色。示例:

                        init() {
                            UINavigationBar.appearance().tintColor = UIColor(colorScheme == .dark ? .white : Color(#colorLiteral(red: 0.2196078449, green: 0.007843137719, blue: 0.8549019694, alpha: 1)))
                            }
                        

                        【讨论】:

                          猜你喜欢
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 2011-10-22
                          • 2017-01-05
                          • 2023-03-19
                          • 1970-01-01
                          • 1970-01-01
                          相关资源
                          最近更新 更多