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!

Add a Comment

Accepted Answer

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?

Answers

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!

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'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?

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