我无法更改导航栏上的提示颜色。我已在viewDidLoad
中尝试了以下代码,但没有任何反应。
self.navigationController?.navigationBar.titleTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.white]
我错过了什么吗?上面的代码是错误的吗?
答案 0 :(得分:15)
我能够在iOS 11上将提示颜色设置为白色,将barStyle设置为黑色。我使用外观代理设置其他颜色属性(如所需的背景颜色):
myNavbar.barStyle = UIBarStyleBlack; // Objective-C
myNavbar.barStyle = .black // Swift
答案 1 :(得分:11)
看起来你对这个问题是正确的。您需要使用UIAppearance
设置iOS 11上的提示文字样式。
我已提交雷达#34758558,titleTextAttributes
属性在iOS 11中停止工作以提示。
好消息是有几种解决方法,我们可以通过使用Xcode的视图层次结构调试器来解决这些问题:
// 1. This works, but potentially changes *all* labels in the navigation bar.
// If you want this, it works.
UILabel.appearance(whenContainedInInstancesOf: [UINavigationBar.self]).textColor = UIColor.white
提示只是一个UILabel。如果我们使用UIAppearance' whenContainedInInstancesOf:
,我们可以很容易地按照我们想要的方式更新颜色。
如果仔细观察,您会注意到UILabel上还有一个包装器视图。它有自己的类可能会响应UIAppearance ...
// 2. This is a more precise workaround but it requires using a private class.
if let promptClass = NSClassFromString("_UINavigationBarModernPromptView") as? UIAppearanceContainer.Type
{
UILabel.appearance(whenContainedInInstancesOf: [promptClass]).textColor = UIColor.white
}
我建议坚持使用更通用的解决方案,因为它不使用私有API。 (应用程序评论等)查看这两种解决方案中的任何一种:
答案 2 :(得分:2)
您可以使用
for view in self.navigationController?.navigationBar.subviews ?? [] {
let subviews = view.subviews
if subviews.count > 0, let label = subviews[0] as? UILabel {
label.textColor = UIColor.white
label.backgroundColor = UIColor.red
}
}
这是一个临时性的解决方法,直到他们修复它为止
答案 3 :(得分:2)
更复杂的版本,以支持新旧iOS
func updatePromptUI(for state: State) {
if (state != .Online) {
//workaround for SOFT-7019 (iOS 11 bug - Offline message has transparent background)
if #available(iOS 11.0, *) {
showPromptView()
} else {
showOldPromptView()
}
}
else {
self.navigationItem.prompt = nil
if #available(iOS 11.0, *) {
self.removePromptView()
} else {
self.navigationController?.navigationBar.titleTextAttributes = nil
self.navigationController?.navigationBar.titleTextAttributes = [NSAttributedStringKey.foregroundColor:UIColor.lightGray]
}
}
}
private func showOldPromptView() {
self.navigationItem.prompt = "Network Offline. Some actions may be unavailable."
let navbarFont = UIFont.systemFont(ofSize: 16)
self.navigationController?.navigationBar.titleTextAttributes = [NSAttributedStringKey.font: navbarFont, NSAttributedStringKey.foregroundColor:UIColor.white]
}
private func showPromptView() {
self.navigationItem.prompt = String()
self.removePromptView()
let promptView = UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 18))
promptView.backgroundColor = .red
let promptLabel = UILabel(frame: CGRect(x: 0, y: 2, width: promptView.frame.width, height: 14))
promptLabel.text = "Network Offline. Some actions may be unavailable."
promptLabel.textColor = .white
promptLabel.textAlignment = .center
promptLabel.font = promptLabel.font.withSize(13)
promptView.addSubview(promptLabel)
self.navigationController?.navigationBar.addSubview(promptView)
}
private func removePromptView() {
for view in self.navigationController?.navigationBar.subviews ?? [] {
view.removeFromSuperview()
}
}
答案 4 :(得分:0)
试试这个: - >
navController.navigationBar.titleTextAttributes = [NSAttributedStringKey.foregroundColor.rawValue: UIColor.red]
答案 5 :(得分:0)
Moshe的第一个答案对我不起作用,因为它改变了系统VC内部的标签,如邮件和文本组成VC。我可以改变那些导航栏的背景,但这会打开另外一堆蠕虫。我不想去私有类路线所以我只更改了自定义导航栏子类中包含的UILabel。
UILabel.appearance(whenContainedInInstancesOf: [NavigationBar.self]).textColor = UIColor.white
答案 6 :(得分:0)
我发现iOS 11的下一个解决方法。
您需要设置为viewDidLoad
navigationItem.prompt = UINavigationController.fakeUniqueText
然后放下一件事
navigationController?.promptLabel(completion: { label in
label?.textColor = .white
label?.font = Font.regularFont(size: .p12)
})
extension UINavigationController {
public static let fakeUniqueText = "\n\n\n\n\n"
func promptLabel(completion: @escaping (UILabel?) -> Void) {
gloabalThread(after: 0.5) { [weak self] in
guard let `self` = self else {
return
}
let label = self.findPromptLabel(at: self.navigationBar)
mainThread {
completion(label)
}
}
}
func findPromptLabel(at view: UIView) -> UILabel? {
if let label = view as? UILabel {
if label.text == UINavigationController.fakeUniqueText {
return label
}
}
var label: UILabel?
view.subviews.forEach { subview in
if let promptLabel = findPromptLabel(at: subview) {
label = promptLabel
}
}
return label
}
}
public func mainThread(_ completion: @escaping SimpleCompletion) {
DispatchQueue.main.async(execute: completion)
}
public func gloabalThread(after: Double, completion: @escaping SimpleCompletion) {
DispatchQueue.global().asyncAfter(deadline: .now() + after) {
completion()
}
}
答案 7 :(得分:0)
我建议使用自定义的mitmdump --set block_global=false
子类并覆盖UINavigationBar
:
layoutSubviews
基本上,我枚举子视图层次结构中的所有UILabel,并检查其文本是否与提示文本匹配。然后,我们将textColor设置为tintColor(随意使用自定义颜色)。这样,我们就不必将私有- (void)layoutSubviews {
[super layoutSubviews];
if (self.topItem.prompt) {
UILabel *promptLabel = [[self recursiveSubviewsOfKind:UILabel.class] selectFirstObjectUsingBlock:^BOOL(UILabel *label) {
return [label.text isEqualToString:self.topItem.prompt];
}];
promptLabel.textColor = self.tintColor;
}
}
类硬编码为提示标签的超级视图。因此,代码更具前瞻性。
将代码转换为Swift并实现辅助方法_UINavigationBarModernPromptView
和recursiveSubviewsOfKind:
留给读者练习。
答案 8 :(得分:0)
您可以尝试以下方法:
import UIKit
class ViewController: UITableViewController {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
updatePrompt()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
updatePrompt()
}
func updatePrompt() {
navigationItem.prompt = " "
for view in navigationController?.navigationBar.subviews ?? [] where NSStringFromClass(view.classForCoder) == "_UINavigationBarModernPromptView" {
if let prompt = view.subviews.first as? UILabel {
prompt.text = "Hello Red Prompt"
prompt.textColor = .red
}
}
navigationItem.title = "This is the title (Another color)"
}
}