There is no public API to set your own attributed text for the large title.
The solution is to navigate down the view hierarchy. You specifically mentioned you wanted to avoid this, but it's the only way to modify the colors while getting the rest of the UINavigationBar
behavior for free.
Of course, you can always create your own UILabel
and set its attributedText
, but you will have to re-create any navigation bar animations and other behavior yourself.
Honestly the simplest solution is to modify your design so it doesn't require a multi-colored large title, as this is currently not supported.
I took a dive down the "spelunking" path, and there are a variety of visual issues with animations snapping back to the original text color.
Here is the code I used if it's useful for anyone trying to achieve a similar effect:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
applyColorStyle(toLabels: findTitleLabels())
}
private func applyColorStyle(toLabels labels: [UILabel]) {
for titleLabel in labels {
let attributedString = NSMutableAttributedString(string: titleLabel.text ?? "")
let fullRange = NSRange(location: 0, length: attributedString.length)
attributedString.addAttribute(NSAttributedStringKey.font, value: titleLabel.font, range: fullRange)
let colors = [UIColor.red, UIColor.orange, UIColor.yellow, UIColor.green, UIColor.blue, UIColor.purple]
for (index, color) in colors.enumerated() {
attributedString.addAttribute(NSAttributedStringKey.foregroundColor, value: color, range: NSRange(location: index, length: 1))
}
titleLabel.attributedText = attributedString
}
}
private func findTitleLabels() -> [UILabel] {
guard let navigationController = navigationController else { return [] }
var labels = [UILabel]()
for view in navigationController.navigationBar.subviews {
for subview in view.subviews {
if let label = subview as? UILabel {
if label.text == title { labels.append(label) }
}
}
}
return labels
}
The downside of the "spelunking" approach is it's not a supported API, meaning that it could easily break in a future update or not work as intended in various edge cases.