'iOS 15 Navigation Bar Transparent
My iOS app uses the storyboard for the UI and uses a custom tint for the background color of the navigation bar.
I have tested my app on the Xcode 13 beta 5 and the navigation bar is "white" and the text on the navigation bar is not visible.
In the apple developer forum at https://developer.apple.com/forums/thread/682420 it states that "In iOS 15, UIKit has extended the usage of the scrollEdgeAppearance, which by default produces a transparent background, to all navigation bars." To restore the old look, you must adopt the new UINavigationBar appearance APIs
I added the following code (from the link above) to the App Delegate "application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions":
if #available(iOS 13, *) {
let navigationController = UINavigationController(navigationBarClass: nil, toolbarClass: nil)
let navigationBar = navigationController.navigationBar
let appearance = UINavigationBarAppearance()
appearance.configureWithOpaqueBackground()
appearance.backgroundColor = UIColor(red: 0.0/255.0, green: 125/255.0, blue: 0.0/255.0, alpha: 1.0)
navigationBar.standardAppearance = appearance;
navigationBar.scrollEdgeAppearance = navigationBar.standardAppearance
navigationBar.isTranslucent = false
}
This does not fix the problem. I still have the custom tint set in the storyboard editor for the navigation bar. Do I need to remove the custom tint or am I implementing the appearance API wrong?
Solution 1:[1]
To use your own colour scheme, use the following:
Swift
// White non-transucent navigatio bar, supports dark appearance
if #available(iOS 15, *) {
let appearance = UINavigationBarAppearance()
appearance.configureWithOpaqueBackground()
UINavigationBar.appearance().standardAppearance = appearance
UINavigationBar.appearance().scrollEdgeAppearance = appearance
}
Objective-c
if (@available(iOS 15.0, *)) {
UINavigationBarAppearance *navBarAppearance = [[UINavigationBarAppearance alloc] init];
navBarAppearance.backgroundColor = [UIColor redColor];
[navBarAppearance configureWithOpaqueBackground];
[UINavigationBar appearance].standardAppearance = navBarAppearance;
[UINavigationBar appearance].scrollEdgeAppearance = navBarAppearance;
}
To get the default translucent behaviour, the way the default was before iOS 15, just set the scrollEdgeAppearance
:
Swift
if #available(iOS 15, *) {
UINavigationBar.appearance().scrollEdgeAppearance = UINavigationBarAppearance()
}
Objective-C
if (@available(iOS 15.0, *)) {
[UINavigationBar appearance].scrollEdgeAppearance = [[UINavigationBarAppearance alloc] init];
}
Solution 2:[2]
There is no need to change anything in the storyboard.
Here is the solution that finally worked when added to the App Delegate application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions
:
//Fix Nav Bar tint issue in iOS 15.0 or later - is transparent w/o code below
if #available(iOS 15, *) {
let appearance = UINavigationBarAppearance()
appearance.configureWithOpaqueBackground()
appearance.titleTextAttributes = [.foregroundColor: UIColor.white]
appearance.backgroundColor = UIColor(red: 0.0/255.0, green: 125/255.0, blue: 0.0/255.0, alpha: 1.0)
UINavigationBar.appearance().standardAppearance = appearance
UINavigationBar.appearance().scrollEdgeAppearance = appearance
}
Note that it was necessary to set the title text attribute to "white" as the title text defaulted to black if this attribute was not specified.
Also note that this should only apply to iOS version 15.0 or later. It does not work for earlier versions as the storyboard navigation bar custom tint is the default behavior.
Solution 3:[3]
If anyone needs the Objective C version of G. Steve's answer
if (@available(iOS 15, *)){
UINavigationBarAppearance *appearance = [[UINavigationBarAppearance alloc] init];
[appearance configureWithOpaqueBackground];
appearance.titleTextAttributes = @{NSForegroundColorAttributeName : UIColor.whiteColor};
appearance.backgroundColor = [UIColor colorWithRed:0.0/255.0 green:125/255.0 blue:0.0/255.0 alpha:1.0];
[UINavigationBar appearance].standardAppearance = appearance;
[UINavigationBar appearance].scrollEdgeAppearance = appearance;
}
Solution 4:[4]
It get sorted for me in interface builder (xcode 13 - tested for iOS 13 and above) and did not need to check for iOS 15 availability (i.e. @available)
- Choose standard and scroll edge appearances for the navigation bar.
- Choose similar settings for both appearances
Good luck
Solution 5:[5]
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
Solution 6:[6]
This code can be put anywhere, not just in the App Delegate to fix the issue on iOS15:
if (@available(iOS 15, *)){
UINavigationBarAppearance *appearance = [[UINavigationBarAppearance alloc] init];
[appearance configureWithOpaqueBackground];
appearance.titleTextAttributes = @{NSForegroundColorAttributeName : UIColor.blackColor};
appearance.backgroundColor = [UIColor colorWithRed:0.0/255.0 green:125/255.0 blue:0.0/255.0 alpha:1.0];
self.navigationController.navigationBar.standardAppearance = appearance;
self.navigationController.navigationBar.scrollEdgeAppearance = appearance;
}
Solution 7:[7]
Xcode 13+
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.
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.backgroundColor = <your tint color>
navigationBar.standardAppearance = appearance
navigationBar.scrollEdgeAppearance = appearance
You can also use the appearance proxy with the code above, but substituting navigationBar.appearance().scrollEdgeAppearance = appearance
for the last line.
Solution 8:[8]
I've created this extension for supporting iOS 15 and iOS 12 for changing navigation bar background (tint) and title colors only in needed places, not over all application.
extension UINavigationBar {
func update(backroundColor: UIColor? = nil, titleColor: UIColor? = nil) {
if #available(iOS 15, *) {
let appearance = UINavigationBarAppearance()
appearance.configureWithOpaqueBackground()
if let backroundColor = backroundColor {
appearance.backgroundColor = backroundColor
}
if let titleColor = titleColor {
appearance.titleTextAttributes = [NSAttributedString.Key.foregroundColor: titleColor]
}
standardAppearance = appearance
scrollEdgeAppearance = appearance
} else {
barStyle = .blackTranslucent
if let backroundColor = backroundColor {
barTintColor = backroundColor
}
if let titleColor = titleColor {
titleTextAttributes = [NSAttributedString.Key.foregroundColor: titleColor]
}
}
}
}
and use it in needed places (in my case it's UI configuration of UIViewController) like this
func configureNavigationController() {
navigationController?.navigationBar.update(backroundColor: .blue, titleColor: .white)
}
Solution 9:[9]
My implementation of navigation bar configuration as opaque and as translucent for iOS 15 and older versions:
extension UINavigationBar {
static let defaultBackgroundColor = UIColor.red
static let defaultTintColor = UIColor.white
func setOpaque() {
if #available(iOS 15, *) {
let appearance = UINavigationBarAppearance()
appearance.configureWithOpaqueBackground()
appearance.backgroundColor = UINavigationBar.defaultBackgroundColor
appearance.titleTextAttributes = [.foregroundColor: UINavigationBar.defaultTintColor]
UINavigationBar.appearance().standardAppearance = appearance
UINavigationBar.appearance().scrollEdgeAppearance = appearance
} else {
setBackgroundImage(UIImage(), for: UIBarPosition.any, barMetrics: UIBarMetrics.defaultPrompt)
shadowImage = UIImage()
barTintColor = UINavigationBar.defaultBackgroundColor
titleTextAttributes = [.foregroundColor: UINavigationBar.defaultTintColor]
}
isTranslucent = false
tintColor = UINavigationBar.defaultTintColor
}
func setTranslucent(tintColor: UIColor, titleColor: UIColor) {
if #available(iOS 15, *) {
let appearance = UINavigationBarAppearance()
appearance.configureWithTransparentBackground()
appearance.titleTextAttributes = [.foregroundColor: titleColor]
standardAppearance = appearance
scrollEdgeAppearance = appearance
} else {
titleTextAttributes = [.foregroundColor: titleColor]
setBackgroundImage(UIImage(), for: UIBarMetrics.default)
shadowImage = UIImage()
}
isTranslucent = true
self.tintColor = tintColor
}
}
Solution 10:[10]
Anybody looking for an objective-c solution, please try out the below code:
if (@available(iOS 15.0, *)) {
UINavigationBarAppearance *navBarAppearance = [[UINavigationBarAppearance alloc] init];
[navBarAppearance configureWithOpaqueBackground];
navBarAppearance.backgroundColor = YOUR_COLOR;
[navBarAppearance setTitleTextAttributes:
@{NSForegroundColorAttributeName:[UIColor whiteColor]}];
self.navigationController.navigationBar.standardAppearance = navBarAppearance;
self.navigationController.navigationBar.scrollEdgeAppearance = navBarAppearance;
}
Solution 11:[11]
I tried various ways but below code worked like Magic for restoring previous version.
if #available(iOS 15, *) {
let appearance = UINavigationBarAppearance()
appearance.configureWithOpaqueBackground()
appearance.backgroundColor = .white
UINavigationBar.appearance().standardAppearance = appearance
UINavigationBar.appearance().scrollEdgeAppearance = appearance
}
Solution 12:[12]
Objective c code : implement this in your viewDidLoad function
if (@available(iOS 15, *)){
UINavigationBarAppearance *appearance = [[UINavigationBarAppearance alloc] init];
[appearance configureWithOpaqueBackground];
appearance.titleTextAttributes = @{NSForegroundColorAttributeName : UIColor.blackColor};
appearance.backgroundColor = [UIColor colorWithRed:0.0/255.0 green:125/255.0 blue:0.0/255.0 alpha:1.0];
self.navigationController.navigationBar.standardAppearance = appearance;
self.navigationController.navigationBar.scrollEdgeAppearance = appearance;
}
Solution 13:[13]
If we need to change the background color and selected and unselected item color, only this code worked in case of me
i have used this to change item appearance tabBarAppearance.stackedLayoutAppearance = tabBarItemAppearance
if #available(iOS 15.0, *) {
let tabBarAppearance = UITabBarAppearance()
let tabBarItemAppearance = UITabBarItemAppearance()
tabBarAppearance.backgroundColor = .white
tabBarItemAppearance.normal.titleTextAttributes = [NSAttributedString.Key.foregroundColor: Constants.Color.appDefaultBlue]
tabBarItemAppearance.selected.titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.black]
tabBarAppearance.stackedLayoutAppearance = tabBarItemAppearance
tabBar.standardAppearance = tabBarAppearance
tabBar.scrollEdgeAppearance = tabBarAppearance
}
Make sure we use this code in TabBar class, to get the desired results, it might not work if we use it in the AppDelegate to set the appearance.
Solution 14:[14]
In AppDelegate.swift
window?.backgroundColor = .white
worked in my case
Solution 15:[15]
To do this with storyboard only, to build over @Atka's answer,
you can set customise title text attributes by opting for "Custom" title attributes
Solution 16:[16]
Here is a version if you want to set custom back button without title and transparent navigation bar
let backImg: UIImage = #imageLiteral(resourceName: "back")
if #available(iOS 15, *) {
let appearance = UINavigationBarAppearance()
appearance.configureWithOpaqueBackground()
appearance.titleTextAttributes = [.foregroundColor: UIColor.black]
appearance.setBackIndicatorImage(backImg, transitionMaskImage: backImg)
appearance.backButtonAppearance.normal.titlePositionAdjustment =
UIOffset(horizontal: -1000.0, vertical: 0)
UINavigationBar.appearance().standardAppearance = appearance
UINavigationBar.appearance().scrollEdgeAppearance = appearance
}
Solution 17:[17]
This code can be put anywhere, not just in the App Delegate to fix the issue on iOS15:
if #available(iOS 15, *) {
let appearance = UINavigationBarAppearance()
appearance.configureWithOpaqueBackground()
appearance.backgroundColor = <desired UIColor>
navigationBar.standardAppearance = appearance;
navigationBar.scrollEdgeAppearance = navigationBar.standardAppearance
}
Solution 18:[18]
Make like this:
let appearance = UINavigationBarAppearance()
appearance.configureWithOpaqueBackground()
appearance.backgroundColor = .red
appearance.titleTextAttributes = [.font:
UIFont.boldSystemFont(ofSize: 20.0),
.foregroundColor: UIColor.white]
// Customizing our navigation bar
navigationController?.navigationBar.tintColor = .white
navigationController?.navigationBar.standardAppearance = appearance
navigationController?.navigationBar.scrollEdgeAppearance = appearance
I wrote a new article talking about it.
https://medium.com/@eduardosanti/uinavigationbar-is-black-on-ios-15-44e7852ea6f7
Solution 19:[19]
I have edited the code shared by @Charlie Seligman as it did not work for me as I had a scroll view in one of my screen. The below code works even if you have a scroll view and a navigation bar.
if #available(iOS 15, *) {
let appearance = UINavigationBarAppearance()
appearance.configureWithOpaqueBackground()
appearance.titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white]
appearance.backgroundColor = UIColor(red: 0.89, green: 0.06, blue: 0.00, alpha: 1.00)
UINavigationBar.appearance().standardAppearance = appearance
UINavigationBar.appearance().scrollEdgeAppearance = appearance
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow