How to change color of ToolbarItem with navigationBarLeading placement in SwiftUI

Viewed 6438

I need a title to be on the left side of a navigation bar. I use the following code:

.toolbar {
    ToolbarItem(placement: .navigationBarLeading) {
        Text("Title")
            .foregroundColor(.black)
    }
}

The problem is that it is displayed blue and as a button. Is it possible to change its color to black somehow? foregroundColor, accentColor do not work. Also, I tried to use a disabled button with Text("Title") inside. But it was displayed grey in that case. Not color, nor PlainButtonStyle were applied.

3 Answers

By default if you add a single Text it's displayed as a Button.

Then, to change its color you need to set the accentColor of the NavigationView (as this button is displayed in the navigation bar):

struct ContentView: View {
    var body: some View {
        NavigationView {
            Text("Test")
                .toolbar {
                    ToolbarItem(placement: .navigationBarLeading) {
                        Text("Title")
                    }
                }
        }
        .accentColor(.black)
    }
}

If you don't want to change the accentColor in the whole NavigationView you can do:

NavigationView {
    VStack {
        //...
    }
    .accentColor(.accentColor)
}
.accentColor(.black)

However, if you want this Text to behave like a Text and not like a Button you can use the following hack:

ToolbarItem(placement: .navigationBarLeading) {
    HStack {
        Text("Title")
        Text("")
    }
    .foregroundColor(.red)
}

Use an empty menu with custom style instead of changing accentColor.

    .toolbar {
         ToolbarItem(placement: .navigationBarTrailing) {
             Menu(content: {
              
             }, label: {
                Text("Hello")
             })
             .menuStyle(RedMenuStyle())
         }
     }



struct RedMenuStyle : MenuStyle {
    func makeBody(configuration: Configuration) -> some View {
        Menu(configuration)
            .font(Font.system(size: 50))
            .foregroundColor(Color.red)
    }
}

Use navigationBarItems should you dispaly only text.

    .navigationBarItems(leading: Text("Hello")
                                 .foregroundColor(Color.red)
                                 .font(Font.system(size: 50)))

Considering, that ToolbarItem does not have any modifiers available, the only possible solution I see is using UIViewRepresentable that seems to ignore toolbars modifications:

.toolbar {
   ToolbarItem(placement: .navigationBarLeading) {
      TitleRepresentation(title: "Test", titleColor: .red)
   }
}

...

struct TitleRepresentation: UIViewRepresentable {
    let title: String
    let titleColor: UIColor
    
    func makeUIView(context: Context) -> UILabel {
        let label = UILabel()
        label.tintColor = titleColor
        label.text = title
        return label
    }
    
    func updateUIView(_ uiView: UILabel, context: Context) {}

    typealias UIViewType = UILabel
}
Related