ios – Change NavigationStack title font, tint, and background in SwiftUI


I am updating the UI of an iOS app, now targeting iOS 16 and above.

In the previous version of the design I was changing the .navigationTitle font, style, and colour using something like this code:

final class AppSettings: ObservableObject {
  @Published var tint: Color = .red {
    didSet { updateNavigationBarAppearance() }
  }

  init() {
    updateNavigationBarAppearance()
  }

  private func updateNavigationBarAppearance() {
    let appearance = UINavigationBarAppearance()
    appearance.configureWithTransparentBackground()
    appearance.largeTitleTextAttributes = [
      .font: UIFont.preferredFont(forTextStyle: .largeTitle).roundedBold,
      .foregroundColor: UIColor(tint).withAlphaComponent(0.9)
    ]
   appearance.titleTextAttributes = [
      .font: UIFont.preferredFont(forTextStyle: .headline).roundedBold,
      .foregroundColor: UIColor(tint).withAlphaComponent(0.9)
    ]
    let navBarAppearance = UINavigationBar.appearance()
    navBarAppearance.standardAppearance = appearance
    navBarAppearance.compactAppearance = appearance
    navBarAppearance.scrollEdgeAppearance = appearance
  }
}

extension UIFont {
  var roundedBold: UIFont {
    guard let descriptor = fontDescriptor
                             .withDesign(.rounded)?
                             .withSymbolicTraits(.traitBold) else { return self }
  return UIFont(descriptor: descriptor, size: pointSize)
  }
}

That gave me something that looks like this:

Rounded navigation title font and colour

But had the bug of this occurring on scrolled views as we were using the appearance.configureWithTransparentBackground(), and transparency doesn’t work in the UINavigationBar.appearance().backgroundColor configuration.

Scrolled content overlapped

With the OS version bump, we can now take advantage of using .toolbarBackground which has fixed the transparency issue when scrolling into the nav area.

However, when that modifier is implemented it affects the font of the navigation title, returning it to the default serif face and black/white colour.

Does anyone know of a way to customise the title while also using the .toolbarBackground modifier?

Though the .navigationTitle accepts a Text element, it seems you cannot customise it, for example:

  .navigationTitle(
    Text("Today")
      .font(.system(.largeTitle, design: .rounded, weight: .black))
  )

As you get this warning in Xcode:

Latest articles

spot_imgspot_img

Related articles

Leave a reply

Please enter your comment!
Please enter your name here

spot_imgspot_img