Reset the appearance of navigation bar in a view controller - ios

I have disabled the bottom border line (shadow image) of the navigation bar using:
self.navigationController.navigationBar.setBackgroundImage(UIImage(), for: .default)
self.navigationController.navigationBar.shadowImage = UIImage()
But after locking the device and unlocking it again the bottom border line appears. I was able to hide it again by using the above code in viewWillAppear:
But I would like to know what's causing the navigation bar to reset to it default configuration each time it appears?
As I am unable to make the shadow line reappear in another ViewController using below code:
self.navigationController.navigationBar.setBackgroundImage(nil, for: .default)
self.navigationController.navigationBar.shadowImage = nil
I would like to know how to reset the navigation bar appearance to make the bottom border line(shadow image) reappear?

Unlocking device will NOT call viewWillAppear, May be you are using a BaseViewController with adding Notification Observer on UIApplicationDidBecomeActiveNotification
Try using Appearance instead on AppDelegate
UINavigationBar.appearance().setBackgroundImage(UIImage(), for: .default)
UINavigationBar.appearance().shadowImage = UIImage()
And Reappear the line again
self.navigationController?.navigationBar.setBackgroundImage(nil, for: .default)
self.navigationController?.navigationBar.shadowImage = nil

You may try to create UINavigationViewController extension with a handy function to do it:
extension UINavigationController {
func resetToDefaultAppearance() {
let appearance = UINavigationBarAppearance()
appearance.configureWithDefaultBackground()
navigationBar.standardAppearance = appearance
navigationBar.scrollEdgeAppearance = appearance
navigationBar.standardAppearance = appearance
navigationBar.compactScrollEdgeAppearance = appearance
}
}
Then call it in your viewWillDisappear:
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
navigationController?.resetToDefaultAppearance()
}

Related

How to add view on top of navigation bar

How to add view above navigation bar?
I have a custom navigation controller and I want to present a view above nav bar (like on the screen), so it should be visible on other ViewControllers
Would be great if the solution will be on storyboard.
Tried to add on UIWindow did't help.
Swift 4.2, Xcode 10+
Okay, from what I can tell (via your comment reply, though it still isn't 100% clear), the best solution to your question would be to make the navigation bar transparent, such that you can see any navigationController-presented view controllers underneath it. For this, I'd suggest the following extension to UIViewController:
extension UIViewController {
func setupTransparentNavigationBarWithBlackText() {
setupTransparentNavigationBar()
//Status bar text and back(item) tint to black
self.navigationController?.navigationBar.barStyle = .default
self.navigationController?.navigationBar.tintColor = .black
}
func setupTransparentNavigationBarWithWhiteText() {
setupTransparentNavigationBar()
//Status bar text and back(item) tint to white
self.navigationController?.navigationBar.barStyle = .blackTranslucent
self.navigationController?.navigationBar.tintColor = .white
}
func setupTransparentNavigationBar() {
self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
self.navigationController?.navigationBar.shadowImage = UIImage()
self.navigationController?.navigationBar.backgroundColor = .clear
self.navigationController?.navigationBar.isTranslucent = true
}
}
Using either of the first two methods in viewWillAppear of your UIViewController subclasses will let you make the navigation bar completely transparent with the statusBar text + wifi/battery indicators black or white as desired. From this, you can then display anything under the navigation bar by pinning your constraints to view.bounds.topAnchor. E.g. for a transparent navigation controller with white statusBar text:
class YourViewController: UIViewController {
override func viewWillAppear(_ animated: Bool) {
setupTransparentNavigationBarWithWhiteText()
}
}

How to remove navigation bar colour clear in swift4?

I want to clear color of navigation bar. In my ViewController there is a background image on that, when i remove color of navigation barTintColor, navigationController.view.background and navigation background image then simulator shows me :-
I have been trying alots of codes but there is no solution found.
I want navigation Bar like that:-
with clear navigation bar color.
Is there any solution, let me know?
Thanks!
You can make the navigation bar transparent in viewWillAppear and remove transparency in viewWillDisappear as follows
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
self.navigationController?.navigationBar.shadowImage = UIImage()
self.navigationController?.navigationBar.isTranslucent = true
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
self.navigationController?.navigationBar.setBackgroundImage(nil, for: .default)
self.navigationController?.navigationBar.shadowImage = nil
self.navigationController?.navigationBar.isTranslucent = false
}
The background image and the back button will be visible
Better you must avoid the navigation bar. Hide the navigation bar in the navigation controller and user custom view in your view controller to avoid this issue.
Swift 5:: Calling below in AppDelegate's didFinishLaunchingWithOptions function does the trick (This will be applied to your all navigationBars though, don't forget to switch your view controllers)
let navBarAppearance = UINavigationBarAppearance()
navBarAppearance.configureWithTransparentBackground()
navigationController?.navigationBar.standardAppearance = navBarAppearance
navigationController?.navigationBar.scrollEdgeAppearance = navBarAppearance

Black Navigation Bar covering image view in collection view header

I have a collection view header who's background contains an image. What I am trying to do is allow for the image to be the background of the navigation controller.
What I have now
This is what I am trying to achieve
I have tried a lot of things so far. I made the navigation bar translucent. I adjusted the edges for extended layout, and I have set the property of navigation controller to be under opaque bars.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
navigationController?.navigationBar.isHidden = false
navigationController?.navigationBar.isTranslucent = true
tabBarController?.tabBar.isHidden = false
tabBarController?.tabBar.barTintColor = UIColor.white
tabBarController?.tabBar.tintColor = UIColor.lightWetAsphalt
self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
self.navigationController!.navigationBar.shadowImage = UIImage()
self.navigationController?.navigationBar.backgroundColor = UIColor.clear
self.edgesForExtendedLayout = []
collectionView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentBehavior.never
}
Note: If i hide the navigation controller, the image view goes under the status bar perfectly fine. For some reason, when I don't hide the navigation bar, thats when it brings up this black view

Transparent navigation bar glitch

I need to make the navigation bar in some view controllers transparent (but with the bar buttons visible).
I wrote the following extension for that.
extension UINavigationBar {
func setTransparent(_ flag: Bool) {
if flag == true {
setBackgroundImage(UIImage(), for: .default)
shadowImage = UIImage()
backgroundColor = .clear
isTranslucent = true
} else {
setBackgroundImage(nil, for: .default)
}
}
}
The default styles for my navigation bars are as follows.
UINavigationBar.appearance().isTranslucent = false
UINavigationBar.appearance().tintColor = .white
UINavigationBar.appearance().barTintColor = UIColor(red: 45/255, green: 93/255, blue: 131/255, alpha: 1)
UINavigationBar.appearance().titleTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.white]
All this works fine. But there's a problem if I have to turn off the transparent effect.
Say in the first view controller I don't need the navigation bar to be transparent.
class FirstViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.navigationBar.setTransparent(false)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.navigationBar.isTranslucent = false
}
}
I push to the second view controller from here. In here, the navigation bar is transparent.
class SecondViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.navigationBar.setTransparent(true)
}
}
Now when I pop back to the previous view controller, I have to explicitly set the isTranslucent property to false. I do that in the viewWillAppear as you can see in the first code snippet.
But the problem is, the navigation bar is black for a second when it happens.
I want this to be smooth. How do I avoid this?
Demo project uploaded here.
I tried the solution described here to a similar question. But it doesn't completely fix my issue. The black bar is gone but the navigation bar doesn't appear for a second just like before as you can see here.
Black navigation bar you see is actually a navigation controller view background color. Try add this code in first view controller viewDidLoad method
navigationController?.view.backgroundColor = navigationController?.navigationBar.barTintColor
Setting the navigation controller view background color did fix the black issue for me, but I was still having the "delay" problem when popping a view controller.
I fixed it by changing the theme of my NavigationController on the willMove method of the view controller being popped. Something like this:
override func willMove(toParent parent: UIViewController?) {
super.willMove(toParent: parent)
guard parent == nil,
let navController = self.navigationController else {
return
}
navController.navigationBar.isTranslucent = false
navController.view.backgroundColor = backgroundColor
navController.navigationBar.barTintColor = barColor
navController.navigationBar.tintColor = tintColor
}
Before Push I use
if let navigator = self.navigationController {
navigator.navigationBar.setBackgroundImage(UIImage(), for: .default)
navigator.navigationBar.titleTextAttributes = [NSAttributedString.Key.foregroundColor : UIColor.black]
navigator.pushViewController(viewController, animated: true)
}
this make the glitch disappear working fine...
note in my case background color was white

Re-Showing the Hairline

I have a two TableViewControllers with Embedded Navigation Controllers. ViewController-1 shows the hairline/shadow under the nav bar and ViewController-2 doesn't show it when I navigate to it. Navigation is done using the Push Segue
To hide the navigation bar in ViewController-2 I adding the following lines in ViewWillAppear the following:
self.navigationController?.navigationBar.setBackgroundImage(UIImage(), forBarMetrics: UIBarMetrics.Default)
self.navigationController?.navigationBar.shadowImage = UIImage()
self.navigationController?.navigationBar.translucent = false
When I use the back button to go back to ViewController-1 the Hairline disappears there too but I do not want it to. Is there anyway to ensure that the hairline doesn't hide in ViewController-1?
I have tried :
self.navigationController?.navigationBar.barStyle = UIBarStyle.Black
and
self.navigationController?.navigationBar.backgroundColor = UIColor.whiteColor()
but without much success.
In the viewWillDisappear (or maybe the viewDidDisappear) method of ViewController-2, add code to undo the changes made in viewWillAppear.
self.navigationController?.navigationBar.setBackgroundImage(nil, forBarMetrics: UIBarMetrics.Default)
self.navigationController?.navigationBar.shadowImage = nil
self.navigationController?.navigationBar.translucent = true

Resources