Can't change UINavigationBar prompt color

前端 未结 9 1503
-上瘾入骨i
-上瘾入骨i 2021-01-04 01:57

I am unable to change the prompt color on my navigation bar. I\'ve tried the code below in viewDidLoad, but nothing happens.

self.navigationCont         


        
相关标签:
9条回答
  • 2021-01-04 02:28

    You can try this:

    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)"
        }
    }
    

    0 讨论(0)
  • 2021-01-04 02:29

    It seems like you're right about this one. You need to use UIAppearance to style the prompt text on iOS 11.

    I've filed radar #34758558 that the titleTextAttributes property just stopped working for prompt in iOS 11.

    The good news is that there are a couple of workarounds, which we can uncover by using Xcode's view hierarchy debugger:

    // 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
    

    The prompt is just a UILabel. If we use UIAppearance's whenContainedInInstancesOf:, we can pretty easily update the color the way we want.

    If you look closely, you'll notice that there's also a wrapper view on the UILabel. It has its own class that might respond to 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
    }
    

    I'd advise sticking to the more general solution, since it doesn't use private API. (App review, etc.) Check out what you get with either of these two solutions:

    0 讨论(0)
  • 2021-01-04 02:29

    More complicated version to support old and new 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()
        }
    }
    
    0 讨论(0)
提交回复
热议问题