iOS: Specify status bar text color when using UINavigationBarAppearance now barstyle is ignored

2.9k views Asked by At

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?

2

There are 2 answers

1
Chu Thin On

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

0
pbm On

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.