barTintColor not working in iOS 15

Hi,

When I run the following code in application(_ :didFinishLaunchingWithOptions) in iOS 15, the bar color turns transparent (thus, showing the black background underneath), while the same code works fine in iOS 14.5:

UINavigationBar.appearance().isTranslucent = false
UINavigationBar.appearance().barTintColor = .red

Here's the screenshots of Simulators running iOS 14.5 and iOS 15:

I'm using Xcode 13 on macOS Big Sur 11.4.

Thanks!

  • deleted

  • Hi, little bit late to the game, but i just got this in my app after compiling with xcode 13.

    I followed the advice from @Rincewind and got it working, with one exception: When you change the appearances, the navigation text, is then black, not white. The back arrow is still white though.

    I managed to sort this out by doing the "largeTextAttributes"-dance : coloredAppearance.titleTextAttributes = [.foregroundColor: UIColor.white] coloredAppearance.largeTitleTextAttributes = [.foregroundColor: UIColor.white]

    However, i am surprised that this is not mentioned by anyone in this thread. Howcome i am the only one having this color issue? Am i missing something?

    Pointers appreciated.

  • Mathias_, you are not alone, I have the same issue, navigation text is black not white.

Accepted Reply

In iOS 15, UIKit has extended the usage of the scrollEdgeAppearance, which by default produces a transparent background, to all navigation bars. The background is controlled by when your scroll view scrolls content behind the navigation bar. Your screenshots indicate that you are scrolled to the top, and so the navigation bar has selected its scrollEdgeAppearance over the standardAppearance that it would use when scrolled, and on previous versions of iOS.

To restore the old look, you must adopt the new UINavigationBar appearance APIs, UINavigationBarAppearance. Remove your existing customizations and do something like this:

let appearance = UINavigationBarAppearance()
appearance.configureWithOpaqueBackground()
appearance.backgroundColor = <your tint color>
navigationBar.standardAppearance = appearance;
navigationBar.scrollEdgeAppearance = navigationBar.standardAppearance

In the general case, it is the last line navigationBar.scrollEdgeAppearance = navigationBar.standardAppearance, which resolves the issue by having the UINavigationBar use the same appearance for both its standard and edge states. Also note that this will cause the scroll view to underlap the navigation bar – we recommend against setting UINavigationBar.isTranslucent = true.

You can also use the appearance proxy with the code above, but substituting navigationBar.appearance().scrollEdgeAppearance = appearance for the last line (as you are constructing your own appearance object – the idea is to just make sure both scrollEdge and standard appearances are the same).

  • Hi, Rincewind. Quick question. How do you change the Navigation Bar's tint color? The classes UINavigationBarAppearance, UIBarAppearance, and UIBarButtonItemAppearance do not include any tintColor property. The only way I found is with the tintColor property of the UINavigationBar, but this is a Legacy property and we are supposed to use appearances objects. For instance, how do you change the color of the image for the Back button? Thanks!

  • Have you tried applying it to UIImagePickerController? No luck when I tried it

  • Any solution on SwiftUI? Is this what is causing really ugly List animations inside NavigationView on 15 where the content goes 'behind' the navigation bar, i.e. FB9536532?

Replies

In iOS 15, UIKit has extended the usage of the scrollEdgeAppearance, which by default produces a transparent background, to all navigation bars. The background is controlled by when your scroll view scrolls content behind the navigation bar. Your screenshots indicate that you are scrolled to the top, and so the navigation bar has selected its scrollEdgeAppearance over the standardAppearance that it would use when scrolled, and on previous versions of iOS.

To restore the old look, you must adopt the new UINavigationBar appearance APIs, UINavigationBarAppearance. Remove your existing customizations and do something like this:

let appearance = UINavigationBarAppearance()
appearance.configureWithOpaqueBackground()
appearance.backgroundColor = <your tint color>
navigationBar.standardAppearance = appearance;
navigationBar.scrollEdgeAppearance = navigationBar.standardAppearance

In the general case, it is the last line navigationBar.scrollEdgeAppearance = navigationBar.standardAppearance, which resolves the issue by having the UINavigationBar use the same appearance for both its standard and edge states. Also note that this will cause the scroll view to underlap the navigation bar – we recommend against setting UINavigationBar.isTranslucent = true.

You can also use the appearance proxy with the code above, but substituting navigationBar.appearance().scrollEdgeAppearance = appearance for the last line (as you are constructing your own appearance object – the idea is to just make sure both scrollEdge and standard appearances are the same).

  • Hi, Rincewind. Quick question. How do you change the Navigation Bar's tint color? The classes UINavigationBarAppearance, UIBarAppearance, and UIBarButtonItemAppearance do not include any tintColor property. The only way I found is with the tintColor property of the UINavigationBar, but this is a Legacy property and we are supposed to use appearances objects. For instance, how do you change the color of the image for the Back button? Thanks!

  • Have you tried applying it to UIImagePickerController? No luck when I tried it

  • Any solution on SwiftUI? Is this what is causing really ugly List animations inside NavigationView on 15 where the content goes 'behind' the navigation bar, i.e. FB9536532?

It worked like a charm! Thank you!

  • Thanks Rincewind, but this fix is changing the title text color in navbar and back button is still white. Any solution for this issue? Thanks

  • self.navigationController.navigationBar.tintColor = [UIColor whiteColor]; It still works.

Add a Comment

I'm seeing this issue too. I'm surprised that the default behavior is this and that it requires configuration now? I also had to set it for all appearance types to make it look better, but there are still cases where the appearance is strange especially in the transitions between view controllers.

  • the transition between viewcontrollers is bugged, theres a few forum topics about it. so hopefully that will be fixed next beta

Add a Comment

I have the same problem. The code has to be inserted in each controller and the transitions between the controllers is buggy (Xcode Beta 2, iOS 15 Beta 2).

My problem is the missing top line in the TabBar. I can solve it only by adding a frame. But the frame would have to be visible only at the top. Does anyone have any ideas? Here is my current solution:

tabBarController?.tabBar.tintColor = "myTintColor"
tabBarController?.tabBar.clipsToBounds = true
tabBarController?.tabBar.layer.borderWidth = 0.5
tabBarController?.tabBar.layer.borderColor = UIColor.lightGray.cgColor

thanks!

*** Update iOS15 Beta 3 / Xcode Beta 3 ***

Since beta 3 the problem seems to be solved in the main controller. But when I switch to a subcontroller, the separator line disappears. It no longer appears when I switch back to the main controller. This is definitely a bug!

Post not yet marked as solved Up vote reply of TN-T Down vote reply of TN-T

We faced a similar problem and are considering resolving it with making sure that we always set the background of the view of our view controllers to something other than clear such as systembackgroundcolor, and ensuring that all of our view controllers use UIRectEdgeAll. Previously some view controllers and especially WKWebViews had a clear background and UIRectEdgeNone.

I'd be curious to hear if this helps for anyone else. I like this approach more as it feels less invasive than changing the appearance of the navigation bar.

This Navigation Bar Transparency problem began when Apple made Dark Mode. I told them about it and Apple fixed it but they have broken the Nav Bar again in iOS 15.

The issue persists on iOS 15 Beta 8. Tried on both light/dark theme.

This doesn't seem to work at all with the iOS 15 RC.

VC1 shows VC2. VC1 and VC2 are fine. Their navigation bars are the correct colour.

VC2 presents an image picker (of your library photos). Nothing I do seems to make the image picker use the right colours.

I've tried to use Rincewind's code to style the picker, but it just shows as light grey, with the nav bar buttons in white. I've implemented navigationController:willShowViewController:animated, but whatever I put in there is completely ignored.

It does seem that Apple decide to change the fundamental behaviour of something, and just assume that developers will change their apps to cope with it How about you give us a heads-up before you break our apps?

  • I also faced the same problem. I can't change navigation background color or navigation bar color for UIImagePickerController. Did you find a different solution?

Add a Comment

I've changed .barTintColor to UINavigationBarAppearance backgroundColor, set to standardAppearance and scrollEdgeAppearance and it works. But if present new ViewController modally with modalPresentationStyle == .fullscreen and dismiss, navigationBar's background color on the first one changed to default.

  • I have exactly the same issue and haven't found a solution, any progress on this for you @Banck?

  • @tonjac The solution is using Xcode 12)

  • I'm doing exactly what you said, and I can't reproduce the issue. Can you post on github a minimal example showing how to experience the problem?

Add a Comment

In my case, when I update to xcode13 and iOS15。 I have found that navigationBar and tabBar turns transparent。 My viewController is embed in UINavigationController

After a series of tests, I found the Settings the backgroundColor of navigationController is best Way to fix this

navigationController?.view.backgroundColor = .yourColor

Once the color is set, everything is fine

  • it's worked for my case, thanks

  • worked for me as well, thanks!

  • it's worked for me as well, thanks!

@cblaze22 asked for an Objective-C version. Here:

UINavigationBarAppearance *navBarAppearance = [[UINavigationBarAppearance alloc] init];
[navBarAppearance configureWithOpaqueBackground];
navBarAppearance.backgroundColor = [UIColor blueColor];
[navBarAppearance setTitleTextAttributes:
        @{NSForegroundColorAttributeName:[UIColor whiteColor]}];

navBar.standardAppearance = navBarAppearance;
navBar.scrollEdgeAppearance = navBarAppearance;
[navBarAppearance release];`
```

After going through all the answers so far and trial and error in interface builder the problem is sorted for me after the following steps: (xcode 13 , iOS 13)

  1. choose standard and scroll edge appearances for the navigation bar.

  1. set both appearances to be the same.

Good luck

Post not yet marked as solved Up vote reply of atka Down vote reply of atka
  • This is exactly what I needed, thanks!

  • Thanks, worked for me in ios 13;

  • This worked, thanks!

In case it helps someone, placing @Rincewind's code snippet in applicationDidBecomeActive restored the pre-iOS15 look of the navigation bar and ensured the navigation controller background view color updated when the user changed between light and dark mode while the app was running.

      let appearance = UINavigationBarAppearance()
      appearance.configureWithOpaqueBackground()
      appearance.backgroundColor = color  // eg .black or .white
      nc.navigationBar.standardAppearance = appearance;
      nc.navigationBar.scrollEdgeAppearance = nc.navigationBar.standardAppearance

In case someone is having issues with navigation title font and color, add the following code to your extension


     if let attributes = self.navigationController?.navigationBar.largeTitleTextAttributes {
        barAppearance.largeTitleTextAttributes = attributes
      }
       
      if let attributes = self.navigationController?.navigationBar.titleTextAttributes {
        barAppearance.titleTextAttributes = attributes
      }

hope it helps

  • After implementing the above solution, the status bar on the view controller turns black. Is there anything to change it to white colour?

  • I have the same issue

  • use overrideUserInterfaceStyle this on UINavigationController to change the status bar color manually. found this here

Add a Comment