How to add view on top of navigation bar - ios

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()
}
}

Related

"PrefersLargeTitles" preventing background color change in all navigation bars

I have a tableViewController as my root view controller.
I've been trying to change the color of the status bar to match something like this:
However, when I set:
navigationController?.navigationBar.prefersLargeTitles = true
And apply:
override func viewDidAppear(_ animated: Bool) {
navigationController?.navigationBar.barTintColor = UIColor.blue
UINavigationBar.appearance().titleTextAttributes = [NSAttributedString.Key(rawValue: NSAttributedString.Key.foregroundColor.rawValue): UIColor.blue]
}
The background color doesn't change at all.
Only when I begin SCROLLING and the navigation bar collapses, do I get a color.
Has anyone else ran into this issue before? I built another viewController to test out "PrefersLargeTitles" WITHOUT a tableview scroll feature. And there was no background color either.

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

How do I create a custom navigationController with image and name?

My goal is to create a UI that looks like this
The only way that I could think of is to embed a navigationController on the UIViewController then add UIView
Storyboard
Code - ProfileViewController
class ProfileViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
navigationBarColor()
}
func navigationBarColor() {
navigationController?.navigationBar.backgroundColor = UIColor(red:0.91, green:0.04, blue:0.51, alpha:1.0)
navigationController?.navigationBar.shadowImage = UIImage()
navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
}
}
Result
Is my approach correct? or do I need to use a different method to achieve this result?
The best way to do this is to make the navigationBar invisible basically. Here is what I did to achieve the look you want:
Step 1:
Add the navigation controller and a view controller and hold control and drag from the navigation controller to the view controller and select root view controller(which i am pretty sure you have already done). Also, drag and drop a UIBarButtonItem onto the navigationBar in the view controller, not the navigationBar in the navigation controller.
Step 2:
Subclass the navigation controller and the view controller, in my example, mine are called CustomNavController.swift and MainVC.swift. In the storyboard, set them as the class of the controllers.
Step 3:
In the class you made for the view controller, set the code in the viewDidLoad to change the background color.
import Foundation
import UIKit
class MainVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor(red: 231/255, green: 11/255, blue: 129/255, alpha: 1)
}
}
And in the navigation controller class, add this code.
import UIKit
class CustomNavController: UINavigationController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.navigationBar.setBackgroundImage(UIImage(), for: .default)
self.navigationBar.shadowImage = UIImage()
self.navigationBar.isTranslucent = true
self.navigationBar.tintColor = .white
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
}
The Result:
Since you are using a navigation controller, you have to set the status bar style to lightContent in the navigation controller subclass like shown above. If you have other view controller that you want the status bar to be black in, you will have to implement the method preferredStatusBarStyle in the class and return .default unless, if the view controller has a navigation controller associated with it, the you would have to implement preferredStatusBarStyle in the navigation controller subclass like I showed in my example. If you have any questions feel free to leave a comment and I will answer when I can.
You can subclass navigation bar, but with that amount of size, i think it's not a good approach. What you are doing seems ok. It's a solution.
Your approach will work. To match your Sketch mockup as closely as possible, here are a few tips:
UINavigationBar's background color should be set using the barTintColor property. This will give the status bar the same background color.
Set the UINavigationBar's barStyle property to black. This will set the status bar's content color to white.
You might notice how the navigation bar's color is slightly different from the view you created beneath it. This is because UINavigationBar is translucent by default, so the background color has a reduced alpha value. You can set the UINavigationBar property isTranslucent to false to fix this.
An alternative approach (without UINavigationController) would involve creating a simple UIView to use as the status bar background, as shown here: https://stackoverflow.com/a/43264566/5223633.
First step, add this 3 lines of codes in your viewDidLoad methods of your controller class:
navigationController?.navigationBar.barTintColor = UIColor(red:0.91, green:0.04, blue:0.51, alpha:1.0)
navigationController?.navigationBar.tintColor = UIColor.white
UIApplication.shared.statusBarStyle = .lightContent
And then, select your info.plist file. When it's opened, add a row by right clicking on it. Give the key name:
View controller-based status bar appearance
and set it's value into:
NO
as boolean value.
see this info.plist screenshot example
Then run it.
You can create custom viewcontroller with Xib file after that load and add its view inside your navigation bar. Hide back button if required and update navigationBar height
accordingly
navigationItem.hidesBackButton = true
navigationController?.navigationBar.frame.size.height = 100
guard let yourCustomView = UINib(nibName: "yourCustomXib", bundle: nil).instantiate(withOwner: nil, options: nil).first as? YourCustomView else {
fatalError("Missing yourCustomXib")
}
navigationController?.navigationBar.addSubview(yourCustomView)

Resources