11

Problem

I have an app that has different colour navigation bars for different flows. Some navigation bars have a light background and require black status bar text. Others have a darker navigation bar and require white status bar text.

As part of the move to iOS15 I have updated an app I am working on to use the UINavigationBarAppearance approach to navigation bar styling. I am able to style everything as I could before other than the status bar color.

Previously I have been using the barStyle property on navigation bar to set the status bar text color.

navigationBar.barStyle = .black

This does not appear to work when using UINavigationBarAppearance.

Sample code

Old styling approach

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let navigationBar = navigationController?.navigationBar
        
        // Style using old approach
        navigationBar?.barTintColor = UIColor.purple
        navigationBar?.titleTextAttributes = [.foregroundColor: UIColor.white]
        
        // Use barStyle to set status bar text color to white
        // This only work when using the old styling approach
        navigationBar?.barStyle = .black
    }

enter image description here

New styling approach

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let navigationBar = navigationController?.navigationBar
        
        // Style nav bar using new Appearance API
        let navBarAppearance = UINavigationBarAppearance()
        navBarAppearance.backgroundColor = UIColor.purple
        navBarAppearance.titleTextAttributes = [.foregroundColor: UIColor.white]

        navigationBar?.standardAppearance = navBarAppearance
        navigationBar?.scrollEdgeAppearance = navBarAppearance
        
        // Use barStyle to set status bar text color to white
        // This only work when using the old styling approach
        navigationBar?.barStyle = .black
    }

enter image description here

Alternatives

Force dark/light mode on the navigation bar

It is possible to make the status bar text white using the property overrideUserInterfaceStyle. To make the status bar text white, set

navigationBar.overrideUserInterfaceStyle = dark

However, this results in menus from buttons in the nav bar in dark mode too which is not what I want.

enter image description here

Subclass UINavigationController

I imagine I could also subclass UINavigationController and explicitly override the preferredStatusBarStyle to force black or white text.

Having to use a subclass everywhere we make new navigation controllers just to specify the status bar text color seems a bit extreme.

Anything else?

I'm not sure if there is a better approach to this?

bencallis
  • 3,478
  • 4
  • 32
  • 58
  • 3
    Thank you for posting this and clearly describing the problem! We are encountering these exact same issues! I will let you know if we find a solution. – JohnVo Oct 07 '21 at 15:51
  • Hi, did you find a solutions to this one by any chance? – Eugene Gordin Oct 29 '21 at 02:03
  • 1
    I have been struggling with it for past couple hours and it looks like the system is trying to match status bar color to navbar's tint color. When I set it to white, status bar is white, if I set it to some random color, it is black. At least that's how it works in my case, there might be other things involved. – Lope Oct 31 '21 at 10:47
  • Any updates? facing the same issue :( – zaitsman Nov 10 '21 at 10:02

2 Answers2

3

I was able to set the status bar text white using:

navController.navigationBar.overrideUserInterfaceStyle = .dark

Note that bencallis, the creator of this question, warns that this solution "results in menus from buttons in the nav bar in dark mode too which is not what I want". I don't use menus like this so that is not a problem for me. Maybe it's not for you too.

pbm
  • 5,081
  • 4
  • 18
  • 31
2

I use both barStyle and overrideUserInterfaceStyle with UINavigationBarAppearance

// statusBarStyle is .black or .default
if case .black = statusBarStyle {
     navigationController?.navigationBar.overrideUserInterfaceStyle = .dark
} else {
    navigationController?.navigationBar.overrideUserInterfaceStyle = .light
}
navigationController?.navigationBar.barStyle = statusBarStyle

See how it works:

enter image description here enter image description here

Ruli
  • 2,592
  • 12
  • 30
  • 40
Chu Thin
  • 21
  • 4
  • This solution works fine. If you use only `navigationController?.navigationBar.overrideUserInterfaceStyle = .dark` then it's not working. – Chetan kasundra Jan 25 '22 at 09:21