9

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.

Ihor Vovk
  • 551
  • 6
  • 11

4 Answers4

20

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)
}
pawello2222
  • 46,897
  • 22
  • 145
  • 209
  • this is an awesome solution - tried that, but didn't know it's only fixable by setting it to the NavigationView.But the text still automatically becomes a button. Only UIViewRepresentable keeps the Text as a Text – Vivienne Fosh Oct 21 '20 at 17:16
  • 1
    @Lonkly This is just how the toolbar works if you add just a Text (in the current version of SwiftUI). If you add two Texts wrapped in a HStack it behaves differently. – pawello2222 Oct 21 '20 at 17:19
  • I am unable to get the VStack { // ... }.accentColor() to work to change the color of just one toolbar item. I am putting the VStack inside ToolbarItem(), around the Text(), like this: ToolbarItem(placement: .navigationBarTrailing) { VStack { Text("hi") }.accentColor(.red). Is this what you meant or am I doing it wrong? – Gary Oct 27 '20 at 19:12
  • @Gary In the first solution it's the `.accentColor(.black)` on NavigationView which changes toolbar items color (not the `.accentColor(.accentColor)` on VStack). And it changes color for all toolbar items. If you want to change the specific item you need the 2nd solution (with `HStack`). – pawello2222 Oct 27 '20 at 20:03
  • Ah, thanks. It works for individual items now. In fact it works with both VStack and HStack as long as I use .foregroundColor() and add an empty Text(""). Hopefully this hack of using an empty text won't break in the next update :) – Gary Oct 27 '20 at 21:53
  • is there a way to set the `accentColor` for all navigation views using UIAppearance ? – JAHelia Apr 23 '22 at 19:38
6

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)))
mahan
  • 12,366
  • 5
  • 48
  • 83
1

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
}
Vivienne Fosh
  • 1,751
  • 17
  • 24
1

For me it worked using tint:

.toolbar {
    ToolbarItem(placement: .navigationBarLeading) {
        Button {

        } label: {
            Image(systemName: "arrow.backward")
                .bold()
        }
    }
}
.tint(.white)
pableiros
  • 14,932
  • 12
  • 99
  • 105