How to change height of navigation bar in Swift 5 - uinavigationbar

I've created my own navigation bar:
let height = 100
let navbar = UINavigationBar()
navbar.frame.size.width = UIScreen.main.bounds.size.width
navbar.frame.size.height = CGFloat(height)
navbar.frame = CGRect(x: 0,
y: 0,
width: navbar.frame.size.width,
height: navbar.frame.size.height)
navbar.barTintColor = Colors.schedulerDarkGray
navbar.titleTextAttributes = [.foregroundColor: Colors.schedulerBlue!]
navbar.tintColor = Colors.schedulerBlue
let navItem = UINavigationItem()
navItem.title = "Add employee"
navItem.rightBarButtonItem = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(cancel))
navbar.items = [navItem]
view.addSubview(navbar)
self.view?.frame = CGRect(x: 0, y: height, width: Int(UIScreen.main.bounds.width), height: (Int(UIScreen.main.bounds.height) - height))
I don't know why I can't set my own height. I can change the x and y position, and width as well.
When I see it in Debug View Hierarchy, it looks like
Do you have any idea why it doesn't work as it should?

I have found solution:
I added this line in view controller ViewDidLoad
self.additionalSafeAreaInsets.top = height
This helped me: https://developer.apple.com/forums/thread/88202#274620

Related

How to add an image and text on the right side of navigation bar

I tried to make the navigation-bar like this but nothing is going on right. I have added rightbarbutton successfully but in the left side I couldn't add the navigation bar.
I have tried these following codes
private func configureItems(){
self.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: nil)
//self.navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .action, target: self, action: nil)
//self.navigationItem.leftBarButtonItem = UIBarButtonItem(image: UIImage(named: "image8"), style: .done, target: self, action: nil)
let customView = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 40))
customView.text = "John Doe"
customView.textAlignment = .left
customView.layer.masksToBounds = true
navigationItem.leftBarButtonItem = UIBarButtonItem(
customView: customView
)
// let customImageView = UIImageView(image:UIImage(named: "image"))
// customImageView.frame = CGRect(x: 0, y: 0, width: 35, height: 35)
// navigationItem.leftBarButtonItem = UIBarButtonItem(
// customView: customView)
let navController = navigationController!
let image = UIImage(named: "image8")!
let imageView = UIImageView(image: image)
let bannerWidth = navController.navigationBar.frame.size.width
let bannerHeight = navController.navigationBar.frame.size.height
imageView.frame = CGRect(x: 0, y: 0, width: bannerWidth, height: bannerHeight)
imageView.contentMode = .scaleAspectFit
imageView.center = navController.navigationBar.center
navigationItem.leftBarButtonItem = UIBarButtonItem(customView: customView)
navigationItem.titleView = imageView

Set background color for top safe area only in iOS 11

I'm new to Swift. I have set my top bar programmatically.It works fine for all versions except for iOS version 11.
I want to change the background color of the safe area in iPhone X. Presently I have just added the following code to hide the status bar.
override var prefersStatusBarHidden: Bool {
return true
}
I have created top bar using code:
//Top Bar
let topBar = UIView(frame:CGRect(x: 0,y: 0, width: width, height: 60))
topBar.backgroundColor = UIColor.white
topBar.layer.shadowColor = UIColor.gray.cgColor
topBar.layer.shadowOffset = CGSize(width: 0, height: 3)
topBar.layer.shadowOpacity = 1
topBar.layer.masksToBounds = false
topBar.layer.shadowRadius = 8.0;
//ImageView - Back Button
let backBtn = UIButton(frame:CGRect(x: 25, y: 18, width: 18, height: 34))
let backBtnImage = UIImage(named: "back_button") as UIImage?
backBtn.setImage(backBtnImage, for: .normal)
backBtn.layer.masksToBounds = true
backBtn.addTarget(self,action:#selector(backButtonClicked),
for:.touchUpInside)
//Label - Title
let titleLabel = UILabel(frame:CGRect(x: width * 0.3, y: 13, width: width * 0.55, height: 40))
titleLabel.text = "Favorites"
titleLabel.contentMode = UIViewContentMode.center
//include all in view
topBar.addSubview(titleLabel)
topBar.addSubview(backBtn)
containerView.addSubview(topBar)
Is there a way in which i can do it without using UINavigationBar or setting status bar.
Hi you can also try this one ,
need to add a view with same background which you set in your header view and add to container parent view .
please refer below code
//Top Bar
let safeAreaView = UIView(frame:CGrect(x: 0,y: 0, width: width, height: 40))
safeAreaView.backgroundColor = UIColor.white
self.view.addSubview(safeAreaView)
let topBar = UIView(frame:CGRect(x: 0,y: 0, width: width, height: 60))
topBar.backgroundColor = UIColor.white
topBar.layer.shadowColor = UIColor.gray.cgColor
topBar.layer.shadowOffset = CGSize(width: 0, height: 3)
topBar.layer.shadowOpacity = 1
topBar.layer.masksToBounds = false
topBar.layer.shadowRadius = 8.0;
//ImageView - Back Button
let backBtn = UIButton(frame:CGRect(x: 25, y: 18, width: 18, height: 34))
let backBtnImage = UIImage(named: "back_button") as UIImage?
backBtn.setImage(backBtnImage, for: .normal)
backBtn.layer.masksToBounds = true
backBtn.addTarget(self,action:#selector(backButtonClicked),
for:.touchUpInside)
//Label - Title
let titleLabel = UILabel(frame:CGRect(x: width * 0.3, y: 13, width: width * 0.55, height: 40))
titleLabel.text = "Favorites"
titleLabel.contentMode = UIViewContentMode.center
//include all in view
topBar.addSubview(titleLabel)
topBar.addSubview(backBtn)
containerView.addSubview(topBar)

Custom titleView changes location after push and pop new screen in stack

I'm trying to implement custom titleView for navigation controller with "title" and "description" labels. If I placed this titleView on first VC, it looks good. If I push second VC into navigation stack and pop it, location of the titleView is changed.
titleView's constraints:
titleLabel.translatesAutoresizingMaskIntoConstraints = false
descriptionLabel.translatesAutoresizingMaskIntoConstraints = false
titleLabel.widthAnchor.constraint(equalTo: widthAnchor).isActive = true
descriptionLabel.widthAnchor.constraint(equalTo: titleLabel.widthAnchor).isActive = true
titleLabel.topAnchor.constraint(equalTo: topAnchor).isActive = true
descriptionLabel.bottomAnchor.constraint(equalTo: bottomAnchor, constant: 2.0).isActive = true
In viewDidLoad of VC I use follow code to insert titleView:
navigationItem.titleView = BarTitleView()
navigationItem.titleView?.bounds = CGRect(x: 0, y: 0, width: view.bounds.width, height: 44)
navigationItem.titleView?.updateConstraints()
I tried to insert follow lines into viewWillAppear (second VC has different bar buttons and it can be root of problem), but nothing changes
navigationItem.titleView?.bounds = CGRect(x: 0, y: 0, width: view.bounds.width, height: 44)
navigationItem.titleView?.updateConstraints()
How can I fixed this issue?
I have created a Title and Subtitle in the Navigation bar without the need for Interface Builder and constraint modification.
My Function to create the title view looks as follows:
class func setTitle(title:String, subtitle:String) -> UIView {
let titleLabel = UILabel(frame: CGRect(x: 0, y: -8, width: 0, height: 0))
titleLabel.backgroundColor = UIColor.clear
titleLabel.textColor = UIColor.white
titleLabel.font = UIFont.boldSystemFont(ofSize: 17)
titleLabel.text = title
titleLabel.sizeToFit()
let subtitleLabel = UILabel(frame: CGRect(x: 0, y: 12, width: 0, height: 0))
subtitleLabel.backgroundColor = UIColor.clear
subtitleLabel.textColor = UIColor.white
subtitleLabel.font = UIFont.systemFont(ofSize: 12)
subtitleLabel.text = subtitle
subtitleLabel.sizeToFit()
// Fix incorrect width bug
if (subtitleLabel.frame.size.width > titleLabel.frame.size.width) {
var titleFrame = titleLabel.frame
titleFrame.size.width = subtitleLabel.frame.size.width
titleLabel.frame = titleFrame
titleLabel.textAlignment = .center
}
let titleView = UIView(frame: CGRect(x: 0, y: 0, width: titleLabel.frame.size.width, height: titleLabel.frame.size.height))
titleView.addSubview(titleLabel)
titleView.addSubview(subtitleLabel)
let widthDiff = subtitleLabel.frame.size.width - titleLabel.frame.size.width
if widthDiff < 0 {
let newX = widthDiff / 2
subtitleLabel.frame.origin.x = abs(newX)
} else {
let newX = widthDiff / 2
titleLabel.frame.origin.x = newX
}
return titleView
}
Then to use the title view in any view controller I just call this line:
self.navigationItem.titleView = Functions.Views.setTitle(title: "Title String", subtitle: "Subtitle String")

UISearchBar and Two buttons in the Navigation Controller

I am trying to add two buttons and a SearchBar to my navigation controller but the alignment is not correct. I have tried almost everything such as changing the size of SearchBar, UIButton or changing the Y positioning but it didn't work. Any idea how to fix this issue?
I am using iOS 11 and Xcode 9
searchController = UISearchController(searchResultsController: nil)
searchController?.searchBar.frame = CGRect(x: 0, y: 0, width: 200, height: 30)
searchController?.delegate = self
searchController?.searchResultsUpdater = self
let refineButton = UIButton.init(type: UIButtonType.custom)
refineButton.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
refineButton.setImage(#imageLiteral(resourceName: "settings-button"), for: UIControlState.normal)
refineButton.widthAnchor.constraint(equalToConstant: 30).isActive = true
refineButton.heightAnchor.constraint(equalToConstant: 30).isActive = true
let refineItem = UIBarButtonItem(customView: refineButton)
navigationItem.leftBarButtonItem = refineItem
navigationItem.titleView = searchController?.searchBar
searchController?.searchBar.sizeToFit()
Please check :
override func viewWillLayoutSubviews() {
searchController?.searchBar.frame = CGRect(x: 0, y: 0, width: 300, height: 30)
searchController?.searchBar.sizeToFit()
}

Add navigation bar to a view controller without a navigation controller

How do you add a navigation bar to a view controller (collection view controller, actually) that is not embedded in a navigation controller? I tried dragging a Navigation Bar onto the view, but it's just not sticking. This is in Swift.
Try putting this code in your viewDidLoad:
let height: CGFloat = 75
let navbar = UINavigationBar(frame: CGRect(x: 0, y: 0, width: UIScreen.mainScreen().bounds.width, height: height))
navbar.backgroundColor = UIColor.whiteColor()
navbar.delegate = self
let navItem = UINavigationItem()
navItem.title = "Title"
navItem.leftBarButtonItem = UIBarButtonItem(title: "Left Button", style: .Plain, target: self, action: nil)
navItem.rightBarButtonItem = UIBarButtonItem(title: "Right Button", style: .Plain, target: self, action: nil)
navbar.items = [navItem]
view.addSubview(navbar)
collectionView?.frame = CGRect(x: 0, y: height, width: UIScreen.mainScreen().bounds.width, height: (UIScreen.mainScreen().bounds.height - height))
height can, of course, be anything you want. And the actions for the UIBarButtons are selectors to whatever function you want. (You also don't need to have buttons at all).
Edits:
Adjusted the collectionView's frame so it would not overlap with UINavigationBar.
Made height a constant so all its references can be changed in one place.
Here is version for swift 5.
class ViewController: UIViewController, UINavigationBarDelegate {
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(toolbar)
toolbar.delegate = self
let height: CGFloat = 75
let navbar = UINavigationBar(frame: CGRect(x: 20, y: 20, width: UIScreen.main.bounds.width, height: height))
navbar.backgroundColor = UIColor.white
navbar.delegate = self
let navItem = UINavigationItem()
navItem.title = "Title"
navItem.leftBarButtonItem = UIBarButtonItem(title: "Left Button", style: .plain, target: self, action: nil)
navItem.rightBarButtonItem = UIBarButtonItem(title: "Right Button", style: .plain, target: self, action: nil)
navbar.items = [navItem]
view.addSubview(navbar)
self.view.frame = CGRect(x: 0, y: height, width: UIScreen.main.bounds.width, height: (UIScreen.main.bounds.height - height))
}
}
Updated answer for Swift 4:
private func addNavigationBar() {
let height: CGFloat = 75
var statusBarHeight: CGFloat = 0
if #available(iOS 13.0, *) {
statusBarHeight = view.window?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0
} else {
statusBarHeight = UIApplication.shared.statusBarFrame.height
}
let navbar = UINavigationBar(frame: CGRect(x: 0, y: statusBarHeight, width: UIScreen.main.bounds.width, height: height))
navbar.backgroundColor = UIColor.white
navbar.delegate = self as? UINavigationBarDelegate
let navItem = UINavigationItem()
navItem.title = "Sensor Data"
navItem.leftBarButtonItem = UIBarButtonItem(title: "Back", style: .plain, target: self, action: #selector(dismissViewController))
navbar.items = [navItem]
view.addSubview(navbar)
self.view?.frame = CGRect(x: 0, y: height, width: UIScreen.main.bounds.width, height: (UIScreen.main.bounds.height - height))
}

Resources