SwiftUI 更新导航栏标题颜色

SwiftUI update navigation bar title color

如何在 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))

有什么帮助吗?

如果您的内容为

struct MyContent : View {
...
}

然后你可以像这样把它放在红色背景的导航视图中:

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

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

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

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

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

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 的完美功能替代品。

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

希望它能奏效。谢谢!!

不需要使用.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())
    }
}

我还没有想出如何在 per-view 的基础上做前景色,但我确实想出了一个简单的背景色解决方法。

如果使用 .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) 的框架高度。

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

主体背景颜色:-

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)

    }
 }

13.4 更新

注意:第二天再看这个,我的一些问题可能是由于我的设置有点不标准造成的:我仍然是 运行ning mojave,但已手动添加13.4 支持文件(通常只能通过 xcode 11.4 获得,这需要 catalina)。我提到这个是因为我 am/was 也有一些标签栏自定义颜色问题,但我只是注意到这些只有在我实际插入 phone 并且正在 运行 应用程序时才会出现来自 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()。您可能想以不同的方式进行操作,但由于其他原因我已经有了该变量...还有一些其他特定于我的应用程序的东西,例如与颜色相关的对象,但您明白了。

这是对我有用的解决方案。您需要从 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")
    }
}

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

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

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

检查此 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)

希望有用。

根据 Arsenius 的回答,我发现让它始终如一地工作的一种优雅方法是继承 UIViewController 并在 viewDidLayoutSubviews().

中进行配置

用法:

VStack {
    Text("Hello world")
        .configureNavigationBar {
            [=10=].navigationBar.setBackgroundImage(UIImage(), for: .default)
            [=10=].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 中,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)
                }
            }
        }
}

肯定已经有一些好的答案,但所有这些都只能涵盖部分工作:

  1. 来自 的出色解决方案 - 给出好的开始点

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

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

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

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

  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([=10=].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: [=12=]) })
         }
     }
    

this will not work for dynamic colors

  1. 因此您可以按如下方式使用它:

     // modifier to `NavigationView`
     .configureNavigationBar {
         [=13=].switchToAppearence(.defaultLight)
     }
    

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

这个答案有效,但如果您遇到 navigationController 在亮模式或暗模式下为 nil 的问题。只需添加这个..不知道它为什么有效。

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

我采取了稍微不同的方法;我只想更改 标题文本颜色,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)
        }
    }
}

这反过来产生:

.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

您可以使用 SwiftUI-Introspect.

单独设置影响 所有 导航栏,而不是设置 appearance()

示例:

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

结果:

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

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

对我有用的解决方案是使用 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)
  }
}

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

init() {
    UINavigationBar.appearance().tintColor = UIColor.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)))
    }

此解决方案基于已接受的答案,该答案不使用任何库,也不在全球范围内应用 UINavigationBarAppearance

此解决方案通过添加 hack 解决了已接受答案的问题(例如不适用于初始视图或不适用于大显示模式)。

注意 我个人不会在生产代码中使用这个 hack,但是看到这些问题可以解决是很有趣的。使用风险自负。

struct NavigationHackView: View {

    @State private var isUsingHack = false

    var body: some View {
        NavigationView {
            List {
                NavigationLink {
                    Text("Detail view")
                        .navigationTitle("Detail view")
                        .navigationBarTitleDisplayMode(.inline)
                } label: {
                    Text("Show details view")
                }
            }
            .navigationTitle("Hack!")
            .background(
                NavigationConfigurator { navigationController in
                    // required for hack to work
                    _ = isUsingHack
                    navigationController.navigationBar.navigationBarColor(.red, titleColor: .white)
                }
            )
            .onAppear {
                // required for hack to work
                DispatchQueue.main.async {
                    isUsingHack.toggle()
                }
            }
            // required for hack to work, even though nothing is done
            .onChange(of: isUsingHack) { _ in }
        }
    }
}

struct NavigationConfigurator: UIViewControllerRepresentable {

    var configure: (UINavigationController) -> Void = { _ in }

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

    func updateUIViewController(
        _ uiViewController: UIViewController,
        context: UIViewControllerRepresentableContext<NavigationConfigurator>
    ) {
        guard let navigationController = uiViewController.navigationController else {
            return
        }
        configure(navigationController)
    }
}

extension UINavigationBar {

    func navigationBarColor(
        _ backgroundColor: UIColor, 
        titleColor: UIColor? = nil
    ) {
        let appearance = UINavigationBarAppearance()
        appearance.configureWithOpaqueBackground()
        appearance.backgroundColor = backgroundColor

        if let titleColor = titleColor {
            appearance.titleTextAttributes = [.foregroundColor: titleColor]
            appearance.largeTitleTextAttributes = [.foregroundColor: titleColor]
            // back button appearance
            tintColor = titleColor
        }

        standardAppearance = appearance
        scrollEdgeAppearance = appearance
        compactAppearance = appearance

        if #available(iOS 15.0, *) {
            compactScrollEdgeAppearance = appearance
        }
    }
}
Post iOS 14 easy way to do:

        protocol CustomNavigationTitle: View {
            associatedtype SomeView: View
            func customNavigationTitle(_ string: String) -> Self.SomeView
        }
        
        extension CustomNavigationTitle {
            func customNavigationTitle(_ string: String) -> some View {
                toolbar {
                    ToolbarItem(placement: .principal) {
                        Text(string).foregroundColor(.red).font(.system(size: 18))
                    }
                }
            }
        }
        
        extension ZStack: CustomNavigationTitle {}
    
    Suppose your root view of view is made with ZStack
    it can be utilised below way
    
    ZStack {
    }. customNavigationTitle("Some title")

基于此https://whosebug.com/a/66050825/6808357我创建了一个扩展程序,您可以在其中同时设置背景颜色和标题颜色。

import SwiftUI

extension View {
    
    /// Sets background color and title color for UINavigationBar.
    @available(iOS 14, *)
    func navigationBar(backgroundColor: Color, titleColor: Color) -> some View {
        let appearance = UINavigationBarAppearance()
        appearance.configureWithTransparentBackground()
        appearance.backgroundColor = UIColor(backgroundColor)

        let uiTitleColor = UIColor(titleColor)
        appearance.largeTitleTextAttributes = [.foregroundColor: uiTitleColor]
        appearance.titleTextAttributes = [.foregroundColor: uiTitleColor]

        UINavigationBar.appearance().standardAppearance = appearance
        UINavigationBar.appearance().scrollEdgeAppearance = appearance
        
        return self
    }
}

使用方法如下:

var body: some View {
    NavigationView {
        Text("Hello world!") // This could be any View (List, VStack, etc.)
        .navigationTitle("Your title here")
        .navigationBar(backgroundColor: .blue, titleColor: .white)
    }
}

编码愉快!