I am attempting to change the color of a navigation title. How can I change the color of a navigation title without doing it in the didFinishLaunchingWithOptions method in the AppDelegate file.
var viewModel: SignUpViewModel? {
didSet {
viewModel?.viewDelegate = self
title = "Sign Up"
}
}
public var navigationBarColor = UIColor() {
didSet {
UINavigationBar.appearance().barTintColor = UIColor(red: 234.0/255.0, green: 46.0/255.0, blue: 73.0/255.0, alpha: 1.0)
UINavigationBar.appearance().tintColor = UIColor.white
UINavigationBar.appearance().titleTextAttributes = [NSAttributedString.Key
.foregroundColor : UIColor.white]
}
}
you can change the navigation bar title color by setting title text attributes
navigationController?.navigationBar.titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.blue]
you can change the navigation bar buttons color by setting tint color
navigationController?.navigationBar.tintColor = UIColor.blue
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?
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];
}
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.
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;
}
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
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
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;
}
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.
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)
}
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
}
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
}
}
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;
}
In AppDelegate.swift
window?.backgroundColor = .white
worked in my case
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;
}
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.
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
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
}
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
}
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
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
}
I want to set the status bar color the same color as the navigation bar. when I try to set the navigation and status bar to the same color the navigation bar always appear in a lighter color than the status bar.
This is what I want:
My result:
Code in AppDelegate:
Status bar:
UIApplication.sharedApplication().statusBarStyle = .Default
let statusBar: UIView = UIApplication.sharedApplication().valueForKey("statusBar") as! UIView
if statusBar.respondsToSelector(Selector("setBackgroundColor:"))
{
statusBar.backgroundColor = UIColor(red: 43/255.0, green: 79/255.0, blue: 133/255.0, alpha: 1.0)
statusBar.tintColor = UIColor(red: 43/255.0, green: 79/255.0, blue: 133/255.0, alpha: 1.0)
}
Navigation bar:
UINavigationBar.appearance().titleTextAttributes = [NSForegroundColorAttributeName: UIColor.whiteColor()]
UINavigationBar.appearance().backgroundColor = UIColor(red: 43/255.0, green: 79/255.0, blue: 133/255.0, alpha: 1.0)
UINavigationBar.appearance().tintColor = UIColor.whiteColor()
UIApplication.sharedApplication().statusBarHidden = false
UIApplication.sharedApplication().statusBarStyle = .Default
Could anyone give me any suggestion on how to solve this problem.
Thanks in advance!
Warning! Do not do any of this in iOS 13 or later, and definitely not in iOS 15 or later. This is outdated code from long ago!
I was able to get the desired result:
Here's the code I used (Swift 3):
let app = UINavigationBar.appearance()
// nav bar color => your color
app.barTintColor = UIColor(red: 43/255.0, green: 79/255.0, blue: 133/255.0, alpha: 1.0)
app.isTranslucent = false
// status bar text => white
app.barStyle = .black
// nav bar elements color => white
app.tintColor = .white
app.titleTextAttributes = [NSForegroundColorAttributeName:UIColor.white]
This line in your code is illegal and will likely get your app banned from the App Store:
let statusBar: UIView = UIApplication.sharedApplication().valueForKey("statusBar") as! UIView
For the status bar, its color in iOS these days is clear. There is no need to set its color, and you are not supposed to do so. The navigation bar is extended up behind the status bar, and thus they will always have the same color because what you are seeing is always the same interface object, the navigation bar.
As for setting the navigation bar's color, don't forget that it is translucent by default. You cannot set its color accurately without making it opaque. Also, you should not be setting its backgroundColor. You should either set its barTintColor or else give it a background image (that is the way to get the best control over its color).
For me the key was to change the isTranslucent attribute:
navigationBar.isTranslucent = false
navigationBar.barTintColor = PlateColors.mainRed
navigationBar.backgroundColor = PlateColors.mainRed
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
based on #matt suggestion to extend navigationbar below status bar, navigation bar must be opaque:
let navigationBar = navigationController?.navigationBar
navigationBar?.isOpaque = true
navigationBar?.setBackgroundImage(UIImage(color: UIColor(white: 0, alpha: 0.5)), for: .default)
navigationBar?.shadowImage = UIImage()
extension UIImage {
convenience init?(color: UIColor) {
let rect = CGRect(x: 0.0, y: 0.0, width: 1.0, height: 1.0)
UIGraphicsBeginImageContext(rect.size)
let context = UIGraphicsGetCurrentContext()
context?.setFillColor(color.cgColor)
context?.fill(rect)
let image: UIImage? = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
guard let cgImage = image?.cgImage else { return nil }
self.init(cgImage: cgImage)
}
}
For anyone who ended up here a little later, like myself (Xcode 13.1, iOS 15.1), this may help:
In iOS13 the status bar background colour is different from the navigation bar in large text mode
It's all about defining the appearances for both standardAppearance and scrollEdgeAppearance and setting their respective background colors.
Personally, did not even need to solve this programmatically:
Navigation Bar Attributes
I have encountered the same problem and I have found that it is not the problem of the status bar but the navigation bar. If you set the background color of navigation bar and a simple UIView to the same, the real color shown will be different. To make the color of navigation bar same as another view:
Wrong Code
navigationBar.backgroundColor = .blue
view.backgroundColor = .blue
Right Code
navigationBar.isTranslucent = false
navigationBar.barTintColor = .blue
view.backgroundColor = .blue
In this case, their color will be the same.
The issues that I would like to change "Tintcolor" for each tabs. But the below code doesn't work at all.
And I added the button image and want to resize it using "UIEdgeInsetsMake". But the button is resized weirdly whenever I touched the button. I don't know why.
And I am using Swift 3.
class MainView: UITabBarController {
var TabFirst = UITabBarItem()
var TabSecond = UITabBarItem()
var TabThird = UITabBarItem()
var TabForth = UITabBarItem()
var TabFifth = UITabBarItem()
override func viewDidLoad() {
super.viewDidLoad()
tabBar.barTintColor = UIColor.white
TabFirst = self.tabBar.items![0]
TabFirst.image = UIImage(named: "btn_1-1")!//.withRenderingMode(UIImageRenderingMode.alwaysOriginal)
TabFirst.imageInsets = UIEdgeInsetsMake(12, 10, 11, 11)
tabBar.items?[0].title = "length"
TabSecond = self.tabBar.items![1]
TabSecond.image = UIImage(named: "btn_2-1")!//.withRenderingMode(UIImageRenderingMode.alwaysOriginal)
tabBar.items?[1].title = "length"
TabThird = self.tabBar.items![2]
TabThird.image = UIImage(named: "btn_3-1")!//.withRenderingMode(UIImageRenderingMode.alwaysOriginal)
tabBar.items?[2].title = "length"
TabForth = self.tabBar.items![3]
TabForth.image = UIImage(named: "btn_4-1")!//.withRenderingMode(UIImageRenderingMode.alwaysOriginal)
tabBar.items?[3].title = "length"
TabFifth = self.tabBar.items![4]
TabFifth.image = UIImage(named: "btn_5-1")!//.withRenderingMode(UIImageRenderingMode.alwaysOriginal)
tabBar.items?[4].title = "length"
}
override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
switch item.tag{
case 0:
print("FirstTab")
UITabBar.appearance().tintColor = UIColor(red: 255/255.0, green: 67/255.0, blue: 99/255.0, alpha: 1.0)
case 1:
print("SecondTab")
UITabBar.appearance().tintColor = UIColor(red: 237/255.0, green: 193/255.0, blue: 53/255.0, alpha: 1.0)
case 2:
print("ThirdTab")
UITabBar.appearance().tintColor = UIColor(red: 70/255.0, green: 183/255.0, blue: 128/255.0, alpha: 1.0)
case 3:
print("ForthTab")
UITabBar.appearance().tintColor = UIColor(red: 12/255.0, green: 195/255.0, blue: 199/255.0, alpha: 1.0)
case 4:
print("FifthTab")
UITabBar.appearance().tintColor = UIColor(red: 105/255.0, green: 72/255.0, blue: 170/255.0, alpha: 1.0)
default:
break
}
}
override func viewWillAppear(_ animated: Bool) {
UIApplication.shared.isStatusBarHidden = false
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
EDIT:
You are missing breaks in your switch statement:
switch item.tag{
Also, you are doing a switch on the tag and I don't see anywhere you have tagged them accordingly in your code. You should get the index of the item instead.
I am not a Swift coder, this is how you do it in Objective-C to give you a hint:
NSInteger indexOfTab = [[self.tabBar items] indexOfObject:item];
Then you do your switch statement of indexOfTab.
Here is the Swift version.:
override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
print("the selected index is : \(tabBar.items.index(of: item))")
}
If you want to individually change the "tintColor" , you should set a custom selectedImage instead.
Beware:
By default, unselected and selected images are automatically created
from the alpha values in the source images. To prevent system
coloring, provide images with alwaysOriginal.
As far as the documentation goes, there are no "tintColor" property for a UITabBarItem.
However, the UITabBar itself has a tintColor property. But this is not setting anything individually.
Tint Color
You can specify a custom tint color for the bar background using the
Tint (barTintColor) field. The default background tint color is white.
Use the Image Tint (selectedImageTintColor) field to specify the bar
item’s tint color when that tab is selected. By default, that color is
blue.
Regarding your resize methods, you should resize your original image instead, or check this question if it does fit your needs. However, the UITabBar and UITabBarItem customizations are limited to what you can read in the documentations.
If you want to further customize things individually, I suggest you search for or create a custom solution instead.
I have a UITabBar of which I want to change the background color of the middle item, but I can't figure out how! (I want to keep the rest of the bar the dark grey color it is).
let barTintColor = UIColor(red: 54/255, green: 54/255, blue: 54/255, alpha: 1.0)
UITabBar.appearance().barTintColor = barTintColor
You can do this by inserting a new subview to your TabBar.
Please check out this answer:
// Add background color to middle tabBarItem
let itemIndex = 2
let bgColor = UIColor(red: 0.08, green: 0.726, blue: 0.702, alpha: 1.0)
let itemWidth = tabBar.frame.width / CGFloat(tabBar.items!.count)
let bgView = UIView(frame: CGRectMake(itemWidth * itemIndex, 0, itemWidth, tabBar.frame.height))
bgView.backgroundColor = bgColor
tabBar.insertSubview(bgView, atIndex: 0)
Hope it helps.
Edit:
If you want to change the background image rather than background color, all you have to do is change the line :
bgView.backgroundColor = bgColor
to imageView with image as background, then add it as a subview. It may look like this:
backgroundView = UIImageView(image: UIImage(named: "tabBarImage"))
bgView.addSubview(backgroundView)