In iOS13 the status bar background colour is different from the navigation bar in large text mode
Solution 1
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 = <insert your color here>
navigationBar.standardAppearance = navBarAppearance
navigationBar.scrollEdgeAppearance = navBarAppearance
}
Solution 2
If the problem is that you'd like to give the navigation bar a color when the large title is showing, use the new UINavigationBarAppearance class.
let app = UINavigationBarAppearance()
app.backgroundColor = .blue
self.navigationController?.navigationBar.scrollEdgeAppearance = app
Solution 3
On iOS 13, navigation bars using large title have a transparent color per Apple human interface guidelines. See more infos here:
In iOS 13 and later, a large title navigation bar doesn’t include a background material or shadow by default. Also, a large title transitions to a standard title as people begin scrolling the content
Solution 4
Universal code
let navBarAppearance = UINavigationBarAppearance()
navBarAppearance.configureWithOpaqueBackground()
navBarAppearance.backgroundColor = // your color
navBarAppearance.shadowImage = nil // line
navBarAppearance.shadowColor = nil // line
UINavigationBar.appearance(whenContainedInInstancesOf: [UINavigationController.self]).standardAppearance = navBarAppearance
UINavigationBar.appearance(whenContainedInInstancesOf: [UINavigationController.self]).scrollEdgeAppearance = navBarAppearance
Solution 5
my navigationBar extension, iOS 13 Swift 5
extension UIViewController {
func configureNavigationBar(largeTitleColor: UIColor, backgoundColor: UIColor, tintColor: UIColor, title: String, preferredLargeTitle: Bool) {
if #available(iOS 13.0, *) {
let navBarAppearance = UINavigationBarAppearance()
navBarAppearance.configureWithOpaqueBackground()
navBarAppearance.largeTitleTextAttributes = [.foregroundColor: largeTitleColor]
navBarAppearance.titleTextAttributes = [.foregroundColor: largeTitleColor]
navBarAppearance.backgroundColor = backgoundColor
navigationController?.navigationBar.standardAppearance = navBarAppearance
navigationController?.navigationBar.compactAppearance = navBarAppearance
navigationController?.navigationBar.scrollEdgeAppearance = navBarAppearance
navigationController?.navigationBar.prefersLargeTitles = preferredLargeTitle
navigationController?.navigationBar.isTranslucent = false
navigationController?.navigationBar.tintColor = tintColor
navigationItem.title = title
} else {
// Fallback on earlier versions
navigationController?.navigationBar.barTintColor = backgoundColor
navigationController?.navigationBar.tintColor = tintColor
navigationController?.navigationBar.isTranslucent = false
navigationItem.title = title
}
}}
How to use:
configureNavigationBar(largeTitleColor: .yourColor, backgoundColor: .yourColor, tintColor: .yourColor, title: "YourTitle", preferredLargeTitle: true)
Set ViewController-based status bar...... to NO in info.plist if you want light Content
If you don't want largeTitles set it to false
Tested on iOS 13, hope this help :)
Related videos on Youtube
![steven](https://lh6.googleusercontent.com/-6Xac27uxXNc/AAAAAAAAAAI/AAAAAAAAD-s/0yn8LLe7RJ4/photo.jpg?sz=256)
steven
Updated on December 22, 2021Comments
-
steven over 2 years
Pre-conditions to reproduce the problem:
- Xcode 11 beta + iOS 13 (latest version until Jun. 12 2019)
- The navigation bar is in Large text mode
- Specify the colour of navigation bar.
The status bar will remain in white in a real device, above the green navigation bar.
Solutions I tried:
- Revert it back to iOS12 will solve it, but we will encounter iOS13 eventually...
- disabling the large text mode will solve it...
- hide the status bar will fix it, but it will cause status text overlapping with navigation bar item.
Any ideas? appreciate any help.
-
Reshad almost 5 yearsso what is the solution for having a large title and wanting a custom bartint color?
-
matt almost 5 years@Reshad Use the UINavigationBarAppearance class.
-
McDonal_11 almost 5 yearsCan u help me on this? Value of type 'UINavigationBar' has no member 'scrollEdgeAppearance'
-
matt almost 5 yearsYes it does. developer.apple.com/documentation/uikit/uinavigationbar/… Remember this is iOS 13 we're talking about.
-
Mike almost 5 years@Reshad see my answer below
-
matt almost 5 yearsMakes no sense to set the appearance background color to red and then make the background color clear.
-
Ely almost 5 yearsYour example code uses a custom
Theme
extension on UIColor, which makes it a bit hard to understand -
CenoX almost 5 yearsThis method has one issue about when user changing their theme (eg. light -> dark ) when app running in background. Other stuff changes its color but only navigation bar tint color remains. You can easily see that. Just run app in simulator and change appearence from Developer setting in Settings app. tried overriding
traitCollectionDidChange
and still got error. any ideas on that? -
Sebastian almost 5 yearsDon't forget about
compactAppearance
! -
ShadeToD almost 5 years@CenoX , I found quick and easy solution for your problem. First , create new color set in assets catalog. Change appearances from "None" to "Any, Light, Dark". Choose whatever colors u want. Second step is to load your custom UIColor in code. Use "let customColor = UIColor(named "CustomColor") , change name"CustomColor" to your asset name. Last step is to assign the color to our bar background.
-
CenoX almost 5 yearsI think that is very good solution @ShadeToD. I'm gonna try to my application, Thanks.
-
Jim B almost 5 yearsBetter use these three UINavigationBar.appearance() statements for universal usage:
UINavigationBar.appearance().standardAppearance = navBarAppearance UINavigationBar.appearance().compactAppearance = navBarAppearance UINavigationBar.appearance().scrollEdgeAppearance = navBarAppearance
-
stepheaw over 4 yearsI'm having a hard time seeing the difference between the before and after
-
Andrew Edwards over 4 yearsIf SO isn't showing them in the browser then I'd try either another screen or Download the images and look at them in review for example.
-
benc over 4 years@stepheaw: there's a thin, very-dark line right on the grey<->white boundary...
-
bgolson over 4 yearsAdd in a call to self.navigationController?.navigationBar.setNeedsLayout() if you're doing this after viewDidLoad()
-
Emon over 4 yearsThank you very much man.I wish i could give you more like for this.
-
Fabio over 4 years@Emon Thx! I'm happy to have helped you :)
-
André Pinto over 4 years@deepak-verma I should have mentioned that I'm using Objective-C and not Swift, so the syntax was correct for me.
-
Pavel Lahoda over 4 yearsWhile this approach works, it is not the best idea to set NavigationBar properties using the UINavigationBarAppearance for each UIViewController instance, as the UINavigationBarAppearance is shared (there is just one appearance at time) - this can lead to rather ugly effects in cases where both Controllers are visible, such as when you perform (slow) swipe-left-edge-to-go-back navigation gesture.
-
Fabio over 4 years@PavelLahoda Your answer is correct, but the new OS creates some problems to show large titles ... The correct approach sometimes does not work and above all very rarely you use the swipe to go back when using the navigation controller but the button created automatically in the child controller ... However to be more secure just disable the swipe to go back (which in iOS is useless and not very functional). In all cases, thanks for your comment, it will certainly be useful for those who will read us later :)
-
Ric Santos over 4 yearsNo need to set
compactAppearance
as "If not set, the standardAppearance will be used instead." -
benc about 4 yearsI just implemented the conventional approach via Xcode 11, but I like your thinking. :)
-
user over 3 yearsObligatory "This is stupid, Apple" comment
-
Starsky over 3 yearsIf you're changing these values dynamically in the app, like letting the user select his own app theme, then you will need to call
navigationController?.navigationBar.layoutSubviews()
in order to apply the changes instantly. -
jxd over 3 yearsWhen doing this, it doesn't match the Statusbar color.
-
Konstantin Nikolsky over 2 yearsDude, you've made my day, thanks.