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
Related
I have tested this on a sample project with 2 view controllers defined in the storyboard using Xcode 11 (iOS 13). The "presenting" view controller is embedded in a navigation controller and has the navigation bar colors set in the viewWillAppear.
The "search" view controller adds a UISearchController in the viewDidLoad and is pushed by the presenting view controller (NOT modal).
With just this setup when the search view controller is displayed the navigation bar has the blue background and red tint color as expected. However when scrolling down and the search bar is displayed the background color of the navigation bar is lost (or changed to what appears to be the default iOS grey / translucent). However if you scroll back up (hide the search bar) or focus on the search bar text field the navigation bar color returns!
Also if you focus on the search bar text field and then cancel (by tapping the Cancel button) the tint color of the navigation bar reverts from red to the default iOS blue as can be noticed by the back bar item.
Any suggestions on resolving this issue?
I have set the navigation bar colors in the viewWillAppear of the search controller too which didn't change this behaviour.
I set isTranslucent to true for the navigation bar in the search controller which seemed to prevent the reverting of the background color but it did not change the reverting of the tint color on cancel.
Presenting View Controller
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.navigationBar.barTintColor = .blue
navigationController?.navigationBar.tintColor = .red
}
Search View Controller
override func viewDidLoad() {
super.viewDidLoad()
self.title = "Search VC"
searchController.dimsBackgroundDuringPresentation = false
searchController.obscuresBackgroundDuringPresentation = false
navigationItem.searchController = searchController
definesPresentationContext = true
}
EDIT
Setting the scrollEdgeAppearance, backButtonAppearance and buttonAppearance as suggested works a treat except for system bar buttons that default to the iOS blue. This can be resolved by setting the UINavigationBar.tintColor but neither that resolves the back button chevron color defaulting on cancel of the search.
if #available(iOS 13.0, *) {
let buttonAppearance = UIBarButtonItemAppearance()
buttonAppearance.configureWithDefault(for: .plain)
buttonAppearance.normal.titleTextAttributes = [.foregroundColor: UIColor.red]
let navigationBarAppearance = UINavigationBarAppearance()
navigationBarAppearance.configureWithOpaqueBackground()
navigationBarAppearance.backgroundColor = .blue
navigationBarAppearance.titleTextAttributes = [.foregroundColor: UIColor.red]
navigationBarAppearance.backButtonAppearance = buttonAppearance
navigationBarAppearance.buttonAppearance = buttonAppearance
navigationBarAppearance.doneButtonAppearance = buttonAppearance
navigationController?.navigationBar.scrollEdgeAppearance = navigationBarAppearance
navigationController?.navigationBar.compactAppearance = navigationBarAppearance
navigationController?.navigationBar.standardAppearance = navigationBarAppearance
} else {
navigationController?.navigationBar.barTintColor = .blue
navigationController?.navigationBar.titleTextAttributes = [.foregroundColor: UIColor.red]
navigationController?.navigationBar.tintColor = .red
}
However when scrolling down and the search bar is displayed the background color of the navigation bar is lost
All of that is normal. New in iOS 13, the expanded nav bar (displaying search bar, large title, etc.) has different appearance from the normal nav bar. Your settings applied only to the normal nav bar because you didn't make them the iOS 13 way. If you want the expanded nav bar to look like the normal nav bar, you have to set its appearance separately and explicitly.
To do so, you need to set the navigation bar's scrollEdgeAppearance. Investigate classes UIBarAppearance, UINavigationBarAppearance, and UIBarButtonItemAppearance (you will need to set the backButtonAppearance explicitly).
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()
}
}
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
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
I have 2 views and the navigation bar colour for View 1 is white and the navigation bar colour for view 2 is green. So when i navigate to view2 from view1 the color changes. But when i tap back the navigation bar colour changes to white and that is expected, but initially a green overlay stays on and disappears quickly.
STEP 1 (View1)
STEP 2 (View2)
STEP 3 (Moving to View1 from View2)
then it suddenly changed to this
Code that i am using is as follows
For view1
override func viewWillAppear(_ animated: Bool) {
self.navigationController?.navigationBar.isTranslucent = false
navigationController?.navigationBar.barTintColor = UIColor(hexString: "#FFFFFF")
self.navigationController?.isNavigationBarHidden = false
self.navigationItem.hidesBackButton = true
let image = UIImage(named: "navBardTitleLogoBG")
self.navigationItem.titleView = UIImageView(image: image)
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 40, height: 40))
imageView.contentMode = .center
}
For view2 the code is as follows
override func viewWillAppear(_ animated: Bool) {
UIView.animate(withDuration: 0.5)
{
self.navigationController?.navigationBar.isTranslucent = false
self.navigationController?.navigationBar.barTintColor = UIColor(hexString: "#14B80E")
self.navigationController?.navigationBar.shadowImage = UIImage()
self.setStatusBarBackgroundColor(color: UIColor(hexString: "#14B80E"))
self.navigationItem.title = "Recipe Book"
self.navigationController?.navigationBar.layoutIfNeeded()
}
Can someone guide me how to get rid of that green overlay thats coming on while tapping the back button.
Thanks in advance
From the way you implement navigationBar (without seeing your code) I assume the way you implement UINavigationController is by manually add it from controller or by dragging navigationBar from storyboard object library instead of embed in NavigationController on your storyboard. If that is correct, you can try from your Xcode menu bar:
Editor > Embed In > NavigationController
It will handle the navigation and navigationBar itself.
If it's not, you can customize the size of your navigationBar/color in viewDidAppear()
I hope it answered your question.