SwiftUI更新导航栏标题颜色

Pra*_*iya 15 navigationbar ios swiftui

如何在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)
            }
Run Code Online (Sandbox Code Playgroud)

我已经尝试过,.foregroundColor(.orange)但是没有用

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

有什么帮助吗?

Tha*_*hir 31

在 iOS 14 中,SwiftUI 提供了一种使用 newtoolbar修饰符自定义导航栏的方法。

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

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

  • 但是您无法设置工具栏的背景颜色,对吗? (11认同)
  • 这并不能回答问题。 (11认同)

小智 25

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

检查此链接

注意:我相信您需要更新此示例中的一些代码,添加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))
    }

}
Run Code Online (Sandbox Code Playgroud)

之后,像这样申请:

.navigationBarColor(backgroundColor: .clear, titleColor: .white)
Run Code Online (Sandbox Code Playgroud)

我希望它会起作用。

  • 这会全局应用颜色。不妨在 AppDelegate 中执行此操作,而无需这里的所有恶作剧。 (4认同)
  • 感谢您的解决方案:) 效果惊人!但是当导航栏标题切换为内联外观时,导航栏高度仍然没有减少?您是否尝试过任何解决方法?先谢谢了 (2认同)
  • 这应该是公认的答案。使用 UIViewControllerRepresentable 会导致很多问题,例如重叠滚动视图,有时根本不改变颜色。 (2认同)

小智 24

我采取了稍微不同的方法;我只想更改标题文本颜色,而不更改NavigationBar. 以此为灵感,我得出了以下结论:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

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

可以这样利用:

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

这又产生:

红色导航标题


ars*_*ius 20

这是不是必须使用.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)
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

并使用它

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

Run Code Online (Sandbox Code Playgroud)

修改后的导航栏

  • 嗯,如果这是场景委托中设置的初始视图,那么第一次似乎不起作用;闭包中的 vc.navigationController 为零。当我从某个地方呈现 VC 时,它会立即重新加载正确的样式... (19认同)
  • 不适用于子视图,即使您在所述子视图中声明“.background”,导航栏也会保持相同的颜色。 (16认同)
  • 使用 viewModifier 而不是 UIViewControllerRepresentable (如 https://filipmolcik.com/navigationview-dynamic-background-color-in-swiftui/ 中所述)解决了许多此类问题,例如滚动视图重叠、颜色在首次加载时不受影响、半透明效果和间歇性性能问题。 (8认同)
  • 不幸的是不适用于*大*显示模式 (4认同)
  • **最新的解决方案**,我也得到了`vc.navigationController` nil,就像其他的一样,我完美地复制了所有代码以确保没有任何错误,但仍然是`导航栏标题颜色`和`导航栏色调颜色`没有改变..然后@gyleg5回答解决了我的问题。[此来源](https://filipmolcik.com/navigationview-dynamic-background-color-in-swiftui/) (3认同)
  • 使用滚动视图,内容位于导航栏下方,解决方案是什么? (2认同)

小智 13

基于 Arsenius 的回答,我发现让它一致工作的一种优雅方式是UIViewControllerviewDidLayoutSubviews().

用法:

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

执行:

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)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这肯定效果更好。在 iOS 14 上测试 (2认同)

Geo*_*e_E 10

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

例子:

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

结果:

结果


Moj*_*ini 10

演示

iOS 14开始,您可以拥有任何您想要的自定义视图(包括具有自定义颜色和字体的自定义文本)

.navigationBarTitleDisplayMode(.inline)
.toolbar {
    ToolbarItem(placement: .principal) {
        VStack {
            Text("Yellow And Bold Title")
                .bold()
                .foregroundColor(.yellow)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

您还可以从iOS 16设置导航栏颜色,例如:

.toolbarBackground(.visible, for: .navigationBar)
.toolbarBackground(.red, for: .navigationBar)
Run Code Online (Sandbox Code Playgroud)

  • 是的,但是如果您需要支持 iOS 14、15 和 16 怎么办?您的示例如何为 16 之前的版本应用红色? (3认同)

Anj*_*iya 8

在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)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

  • 这在全球范围内有效,并将影响应用程序中的所有其他视图。 (6认同)

Imr*_*ran 6

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)
}
Run Code Online (Sandbox Code Playgroud)


Dra*_*gos 6

我开发了一个自定义 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()
    }
}

Run Code Online (Sandbox Code Playgroud)

您可以在此处查看:有关说明的完整示例:

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


And*_*lva 6

基于此/sf/answers/4623557781/,我创建了一个扩展,您可以在其中同时设置背景颜色和标题颜色。

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
    }
}
Run Code Online (Sandbox Code Playgroud)

使用方法如下:

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)
    }
}
Run Code Online (Sandbox Code Playgroud)

快乐编码!

  • 这是为了全局外观,因此在设置全局状态时对其进行视图扩展是没有意义的。 (5认同)

Shi*_*esh 5

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

这是主体背景颜色:-

struct ContentView: View {

var body: some View {

 Color.red
.edgesIgnoringSafeArea(.all)

 }

}
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

对于导航栏:-

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

    }

    }

  }
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

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

struct ContentView: View {

@State var msg = "Hello SwiftUI"

var body: some View {

        Text(msg).padding()
            .foregroundColor(.white)
            .background(Color.pink)

    }
 }
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明