简体   繁体   English

多种颜色的大导航栏文本

[英]Large Navigation Bar Text With Multiple Colors

iOS 11 introduces the option for larger text in the Navigation Bar. iOS 11在导航栏中引入了大文本选项。 I would like to have a title that uses multiple colors. 我想要一个使用多种颜色的标题。 For example: 例如:

在此输入图像描述

It's fairly easy to set the title, and even to change the color of the entire title: 设置标题相当容易,甚至可以更改整个标题的颜色:

[[self navigationItem] setTitle: @"Colors"];
[[[self navigationController] navigationBar] setLargeTitleTextAttributes: @{NSForegroundColorAttributeName: [UIColor colorFromHex: redColor]}];

What I can't figure out is how to change just part of the title. 我无法弄清楚的是如何改变标题的一部分。 For example, a way to select the range like this – NSRangeMake(0, 1) – so that I could apply a color to it. 例如,一种选择这样的范围的方法 - NSRangeMake(0, 1) - 这样我就可以为它应用颜色。

This must be possible, right? 这一定是可能的,对吧?

There is no public API to set your own attributed text for the large title. 没有公共API可以为大型标题设置您自己的属性文本。

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. 您特别提到过您想要避免这种情况,但这是修改颜色的唯一方法,同时免费获取其余的UINavigationBar行为。

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. 当然,您始终可以创建自己的UILabel并设置其attributedText ,但您必须自己重新创建任何导航栏动画和其他行为。

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. “探索”方法的缺点是它不是受支持的API,这意味着它可能很容易在未来的更新中中断,或者在各种边缘情况下无法正常工作。

That's no easy feat unfortunately, it's not officially supported. 不幸的是,这并非易事,它没有得到官方的支持。 Here's a few ways I'd consider: 以下是我考虑的几种方法:

• Override layoutSubiews() in a navigation bar subclass. •覆盖导航栏子类中的layoutSubiews()。 Traverse the view hierarchy, and mess with the UILabel to apply attributes. 遍历视图层次结构,并使用UILabel来应用属性。 I wouldn't recommend this, I've moved away from doing something similar - the iOS 11 navigation bar has a seemingly complex and unpredictable behavior. 我不推荐这个,我已经放弃了做类似的事情 - iOS 11导航栏有一个看似复杂和不可预测的行为。 Things like interactive gestures don't always play nice with whatever you tack on. 像交互式手势这样的东西并不总能与你所擅长的任何东西都很好。 Your case is a little more simple than mine was though, so there's a chance this may work fine. 你的情况比我的情况稍微简单一点,所以有可能这可能会很好。

• Create your own navigation bar style view from scratch - one that doesn't inherit from UINavigationBar. •从头开始创建自己的导航栏样式视图 - 不从UINavigationBar继承的视图。 This is the route I ended up taking when doing something similar. 这是我在做类似事情时最终采取的路线。 It's more work, and won't mirror future changes Apple make to the visual style - but on the other hand, your app will look the same even across older iOS versions, and you have complete control. 这是更多的工作,并不会反映Apple对视觉风格的未来变化 - 但另一方面,即使在较旧的iOS版本中,您的应用也会看起来相同,并且您可以完全控制。

• Hide the nav bar separator, revert it to a non-large size, and place your own view underneath it mimicking the look (the background is a visual effect view with a .extraLight blur style) - you can place a custom label inside this view. •隐藏导航栏分隔符,将其恢复为非大尺寸,并将自己的视图放在其下方,模仿外观(背景是具有.extraLight模糊样式的视觉效果视图) - 您可以在其中放置自定义标签视图。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM