In Ios13 the Status Bar Background Colour Is Different from the Navigation Bar in Large Text Mode

In iOS13 the status bar background colour is different from the navigation bar in large text mode

No hacks or funkiness required here. The key is defining the desired appearance and setting this value on BOTH the nav bar's standardAppearance AND its scrollEdgeAppearance. I have the following in the init for my base navigation controller subclass for my entire app:

if #available(iOS 13.0, *) {
let navBarAppearance = UINavigationBarAppearance()
navBarAppearance.configureWithOpaqueBackground()
navBarAppearance.titleTextAttributes = [.foregroundColor: UIColor.white]
navBarAppearance.largeTitleTextAttributes = [.foregroundColor: UIColor.white]
navBarAppearance.backgroundColor =
navigationBar.standardAppearance = navBarAppearance
navigationBar.scrollEdgeAppearance = navBarAppearance
}

Sample Image

iOS13 Navigation bar large titles not covering status bar

The official way to customize the UINavigationBar, pre iOS 13, is this:

// text/button color
UINavigationBar.appearance().tintColor = .white
// background color
UINavigationBar.appearance().barTintColor = .purple
// required to disable blur effect & allow barTintColor to work
UINavigationBar.appearance().isTranslucent = false

iOS 13 has changed how navigation bars work, so you'll need to do things slightly differently to support both old & new:

if #available(iOS 13.0, *) {
let appearance = UINavigationBarAppearance()
appearance.backgroundColor = .purple
appearance.titleTextAttributes = [.foregroundColor: UIColor.white]
appearance.largeTitleTextAttributes = [.foregroundColor: UIColor.white]

UINavigationBar.appearance().tintColor = .white
UINavigationBar.appearance().standardAppearance = appearance
UINavigationBar.appearance().compactAppearance = appearance
UINavigationBar.appearance().scrollEdgeAppearance = appearance
} else {
UINavigationBar.appearance().tintColor = .white
UINavigationBar.appearance().barTintColor = .purple
UINavigationBar.appearance().isTranslucent = false
}

Status bar and navigation bar does not seems to have the same color iOS Swift

To achieve the desired result, set the status bar style to default and set the UINavigationBar.appearance().barTintColor to the required color.

UINavigationBar.appearance().titleTextAttributes = [NSForegroundColorAttributeName: UIColor.whiteColor()]
UINavigationBar.appearance().barTintColor = UIColor(red: 43/255.0, green: 79/255.0, blue: 133/255.0, alpha: 1.0)
UIApplication.sharedApplication().statusBarStyle = .Default

How do I prevent iOS 13's Dark Mode from changing the text color in my app's status bar?

iOS 13 Solution(s)

UINavigationController is a subclass of UIViewController! (who knew )

Therefore, when presenting view controllers embedded in navigation controllers, you're not really presenting the embedded view controllers; you're presenting the navigation controllers! UINavigationController, as a subclass of UIViewController, inherits preferredStatusBarStyle and childForStatusBarStyle, which you can set as desired.

Any of the following methods should work:

  1. Opt out of Dark Mode entirely

    • In your info.plist, add the following property:
      • Key - UIUserInterfaceStyle (aka. "User Interface Style")
      • Value - Light
  2. Override preferredStatusBarStyle within UINavigationController

    • preferredStatusBarStyle (doc) - The preferred status bar style for the view controller

    • Subclass or extend UINavigationController

        class MyNavigationController: UINavigationController {
      override var preferredStatusBarStyle: UIStatusBarStyle {
      .lightContent
      }
      }

      OR

        extension UINavigationController {
      open override var preferredStatusBarStyle: UIStatusBarStyle {
      .lightContent
      }
      }

  3. Override childForStatusBarStyle within UINavigationController

    • childForStatusBarStyle (doc) - Called when the system needs the view controller to use for determining status bar style
    • According to Apple's documentation,

    "If your container view controller derives its status bar style from one of its child view controllers, [override this property] and return that child view controller. If you return nil or do not override this method, the status bar style for self is used. If the return value from this method changes, call the setNeedsStatusBarAppearanceUpdate() method."

    • In other words, if you don't implement solution 3 here, the system will fall back to solution 2 above.

    • Subclass or extend UINavigationController

        class MyNavigationController: UINavigationController {
      override var childForStatusBarStyle: UIViewController? {
      topViewController
      }
      }

      OR

        extension UINavigationController {    
      open override var childForStatusBarStyle: UIViewController? {
      topViewController
      }
      }

    • You can return any view controller you'd like above. I recommend one of the following:

      • topViewController (of UINavigationController) (doc) - The view controller at the top of the navigation stack
      • visibleViewController (of UINavigationController) (doc) - The view controller associated with the currently visible view in the navigation interface (hint: this can include "a view controller that was presented modally on top of the navigation controller itself")

Note: If you decide to subclass UINavigationController, remember to apply that class to your nav controllers through the identity inspector in IB.

Edits: Strikethrough edits were made to remove extensions as a suggested answer. Other developers noted that they stopped working in Xcode 11.4 and Apple's documentation discourages the use of this ambiguous behavior.

P.S. My code uses Swift 5.1 syntax /p>

New UINavigationBar appearance in detail pane of UISplitViewController in iOS 13

The workaround you found is the 'official' way to disable this behavior, as explained in a thread on Twitter by David Duncan who is on the iOS System Experience team at Apple.

to control what happens when the UINavigationBar is completely
unfurled, you want to set the scrollEdgeAppearance. By setting
standardAppearance and scrollEdgeAppearance to the same values, you
will get a bar that doesn't change.

An Apple app that does not disable this behavior is the Settings app.



Related Topics



Leave a reply



Submit