BarButton Item defaulting to center of navigation bar - swift

Im adding a BarButtonItem to a Navigation Bar. This Navigation Controller and Bar don't come from the storyboard and are instead generated programmatically. An issue I've noticed because of this is that the location any BarButton Items are in the center of the navigation bar. Whether it be a RightBarButton or LeftBarButton, the button always appears in the center of the bar. My suspicion is that the available space for button items is zero, causing the buttons to default to the center location. I've attached my code below. Where does the issue arise from?
Creating navigation controller programmatically:
let popoverContent = Itinerary()
popoverContent.parentController = self
let nav = UINavigationController(rootViewController: popoverContent)
nav.modalPresentationStyle = UIModalPresentationStyle.popover
let popover = nav.popoverPresentationController
popover?.sourceView = self.view
nav.navigationBar.barTintColor = UIColor.init(red: 154/255, green: 203/255, blue: 231/255, alpha: 1)
self.present(nav, animated: true, completion: nil)
Adding the BarButtonItems from inside the Itinerary View:
let button = UIButton.init(frame: CGRect.init(x: 0, y: 0, width: 40, height: 40))
let img = UIImage.init(named: "xbutton")
button.setImage(img, for: UIControlState.normal)
button.imageView?.contentMode = .scaleAspectFit
button.addTarget(self, action: #selector(dismissItin), for: .touchUpInside)
let Barbutton = UIBarButtonItem.init(customView: button)
self.navigationItem.rightBarButtonItem = Barbutton

Related

titleView of Navigation item moved to the left?

I have an app with a left (hamburger) navigationItem.leftBarButtonItem and we've set the titleView to the logo of the company. The problem is that they want the logo next to the hamburger. The hamburger button is set in the Storyboard's ViewController and the logo is programmatically, like this:
let logo = UIImage(named: "logo.png")
let imageView = UIImageView(image:logo)
imageView.frame = CGRect(x: 0, y: 0, width: 120, height: 60)
navigationItem.titleView = imageView
Is there a way to move it to the left?
UPDATE:
Regarding the suggestions to use leftBarButtonItems
I've done this in another UIViewController and the result wasn't as I expected it to be.
Here's the code:
let logo = UIImage(named: "logo")!
let karambaButton = UIBarButtonItem(image: logo, style: .plain, target: self, action: nil)
let backBTN = UIBarButtonItem(image: UIImage(named: "back"), style: .plain, target: navigationController, action: #selector(UINavigationController.popViewController(animated:)))
navigationItem.leftBarButtonItems = [backBTN, logoButton]
And here's the result of it:
(The dark block is the image, I had to cover it up because it's a client)
You can set multiple left bar button items by acessing:
navigationItem.leftBarButtonItems = [barItem1, barItem2]
Same with the right side. :)
You can also set auto layout programmatically.
imageView.translatesAutoresizingMaskIntoConstraints = false
let horizontalConstraint = imageView.leadingAnchor.constraint(equalTo: hamburgerButton.trailingAnchor, constant: 10)
let verticalConstraint = newView.centerYAnchor.constraint(equalTo: hamburgerButton.centerYAnchor)
let widthConstraint = newView.widthAnchor.constraint(equalToConstant: 120)
let heightConstraint = newView.heightAnchor.constraint(equalToConstant: 120)
imageView.addConstraints([horizontalConstraint, verticalConstraint, widthConstraint, heightConstraint])
UINavigationItem has a property named leftBarButtonItems.
Put your logo imageView into the customView property of a UIBarItem and size it correctly and you should be all set. Just add it to the the array along with the hamburger button.
edited to add -- try using a custom view, that is:
if let logo = UIImage(named: "logo") {
let imageView = UIImageView(image:logo)
let karambaButton = UIBarButtonItem(customView: imageView)
let backBTN = UIBarButtonItem(image: UIImage(named: "back"), style: .plain, target: navigationController,
action: #selector(UINavigationController.popViewController(animated:)))
navigationItem.leftBarButtonItems = [backBTN, logoButton]
}

I am trying to create a UIbarButtonItem whose width and height is equal to 70% of the height of the navigationbar?

I am trying to write an extension fo UIBarButtonItem. I would like to use auto layout so that the UIBarButtonItem's width and height is 70% of the height of the UINavigationBar. When I implement this extension, i am getting the following auto layout errors:
import UIKit
extension UIBarButtonItem {
static func menuButton(target: Any?, action: Selector, imageName: String, navigationBar: UINavigationBar) -> UIBarButtonItem{
let button = UIButton.init(type: .system)
let image = UIImage.init(named: imageName)
button.setBackgroundImage(image, for: .normal)
button.addTarget(target, action: action, for: .touchUpInside)
let menuButton = UIBarButtonItem.init(customView: button)
menuButton.customView?.translatesAutoresizingMaskIntoConstraints = false
menuButton.customView?.widthAnchor.constraint(equalTo: navigationBar.heightAnchor, multiplier: 0.7).isActive = true
menuButton.customView?.heightAnchor.constraint(equalTo: navigationBar.heightAnchor, multiplier: 0.7).isActive = true
return menuButton
}
}
Implementation:
let rightButton = UIBarButtonItem.menuButton(target: self, action: #selector(editCells), imageName: "expand", navigationBar: navigationController!.navigationBar)
navigationItem.rightBarButtonItem = rightButton
Error message in console:
Terminating app due to uncaught exception 'NSGenericException', reason: 'Unable to activate constraint with anchors <NSLayoutDimension:0x600001be1180 "UIButton:0x7ff5d6d16b80.width"> and <NSLayoutDimension:0x600001be25c0 "UINavigationBar:0x7ff5d911a2f0.height"> because they have no common ancestor. Does the constraint or its anchors reference items in different view hierarchies? That's illegal.'
You can create custom view for your navigationBar custom button and set properties for whatever you want like this:
func addRightButton() {
let barButtonView = UIView(frame: CGRect(origin: .zero, size: CGSize(width: 180, height: 40)))
barButtonView.backgroundColor = UIColor.red
let navigationBarHeightWithRatio = (navigationController?.navigationBar.frame.height ?? 100) * 0.7
let customBarButton = UIButton(frame: CGRect(x: 0, y: 8, width: navigationBarHeightWithRatio, height: navigationBarHeightWithRatio))
customBarButton.setImage(UIImage(named: "your_image_name"), for: .normal)
customBarButton.setTitle("title", for: .normal)
customBarButton.addTarget(self, action: #selector("<your_action_function>"), for: .touchUpInside)
barButtonView.addSubview(customBarButton)
let rightBarButton = UIBarButtonItem(customView: barButtonView)
navigationItem.rightBarButtonItem = rightBarButton
}
Note:
You can customize width different width, height values and x, y positions.
I hope it is works.
Enjoy.
The error message is clear. When you say:
let rightButton = UIBarButtonItem.menuButton(
target: self, action: #selector(editCells),
imageName: "expand",
navigationBar: navigationController!.navigationBar)
... and the menuButton method runs, at that moment, you are trying to form a constraint relationship between the button and the navigation bar at a time when the button is not in the navigation bar. That, as the error message tells you, is illegal.
(I doubt that the goal you have outlined is possible at all, but that's another story. I'm just explaining the error message.)

Set Nav Bar's color without using .barTintColor?

I am trying to display a user picture in place of the rightBarButton but setting barTintColor of the UINavigationBar tints the image.
In the AppDelegate, tried:
UINavigationBar.appearance().barTintColor = .blue
In the viewDidLoad, tried:
self.navigationController?.navigationBar.backgroundColor = .blue
self.navigationController?.navigationBar.tintColor = .blue
self.navigationController?.navigationBar.barTintColor = .blue
To set the image:
let avatarBtn = UIButton(type: .custom)
avatarBtn.frame = CGRect(x: 0.0, y: 0.0, width: 30, height: 30)
avatarBtn.setImage(UIImage(named:"myAvatar")?.withRenderingMode(.alwaysOriginal), for: .normal)
let menuBarItem = UIBarButtonItem(customView: avatarBtn)
menuBarItem.tintColor = .clear
self.navigationItem.rightBarButtonItem = menuBarItem
None of these have worked. How can you setup a multi-colored nav bar button without a tint?
Thanks in advance
Change tintColor.
tintColor : The tint color to apply to the navigation items and bar button items.
I used your code but in my case i got expected result. Which image type you are using?
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.navigationBar.backgroundColor = .blue
self.navigationController?.navigationBar.tintColor = .blue
self.navigationController?.navigationBar.barTintColor = .blue
let avatarBtn = UIButton(type: .custom)
avatarBtn.frame = CGRect(x: 0.0, y: 0.0, width: 30, height: 30)
avatarBtn.setImage(UIImage(named:"myAvatar1")?.withRenderingMode(.alwaysOriginal), for: .normal)
let menuBarItem = UIBarButtonItem(customView: avatarBtn)
menuBarItem.tintColor = .clear
self.navigationItem.rightBarButtonItem = menuBarItem
}

Swift: Programmatically add UIButton above keyboard

I'm trying to add a (custom with a corner radius of 25.0) UIButton to hover just above the keyboard in my view controller.
I have tried accomplishing this on my own by adding this button to a toolbar with the following code, however, I am not looking for a toolbar:
let toolbar = UIToolbar(frame: CGRectMake(0, 0, self.view.frame.size.width, 50))
toolbar.barStyle = UIBarStyle.Default
loginButton.titleLabel?.textColor = UIColor.whiteColor()
loginButton.backgroundColor = UIColor.redColor()
loginButton.titleLabel?.text = "Sign Up"
loginButton.addTarget(self, action: #selector(signUp), forControlEvents: .TouchUpInside)
let customButton = UIBarButtonItem(customView: loginButton)
toolbar.items = [customButton]
toolbar.sizeToFit()
//...
//When credentials are valid, show/enable button...
usernameEmailField.inputAccessoryView = toolbar
How can I add a UIButton to hover just above the keyboard at all times?
Thank you.
This one works for me. Please try this
//create toolbar object
let doneToolBar: UIToolbar = UIToolbar(frame:CGRect(x: 0, y: 0, width: UIScreen.mainScreen().bounds.size.width, height: 44))
doneToolBar.barStyle = UIBarStyle.BlackTranslucent
//add barbuttonitems to toolbar
let flexsibleSpace: UIBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: nil, action: nil) // flexible space to add left end side
let doneButton: UIBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Done, target: self, action: #selector(UITextField.didPressDoneButton))
doneToolBar.items = [flexsibleSpace,doneButton]
//assing toolbar as inputAccessoryView
textField.inputAccessoryView = doneToolBar
doneToolBar.sizeToFit()

How to remove the uiview I created from navigationController when I move forward or back to next page?

I created a view programmatically and added to the navigationController as subview. The problem that I am facing now is that the view is not removed when i move forward to next page or the previous page. What can be done to remove the view or include the view in a particular view controller of the navigation controller only?
self.footerView = UIView(frame: CGRectMake(0, UIScreen.mainScreen().bounds.height - 40, tableView.frame.size.width, 40))
self.footerView.tag == 1
footerView.backgroundColor = themeColor
let totalLabel = UILabel(frame: CGRectMake(16, 8, footerView.frame.width/2, 30))
totalLabel.text = "Rs. 200"
totalLabel.textColor = UIColor.whiteColor()
let button = UIButton(type:UIButtonType.Custom)
button.frame = CGRectMake(footerView.frame.width/2 - 16, 8, footerView.frame.width/2, 30)
button.layer.masksToBounds = true
button.setTitle("Save and Continue", forState: .Normal)
button.setTitleColor(UIColor.whiteColor(), forState: .Normal)
button.addTarget(self, action: "saveButonPressed:", forControlEvents: .TouchUpInside)
button.layer.borderColor = UIColor.whiteColor().CGColor
button.layer.borderWidth = 2
button.layer.cornerRadius = 8
footerView.addSubview(totalLabel)
footerView.addSubview(button)
self.navigationController?.view.addSubview(footerView)
Create the same View in ViewController.
let customView = //your view creation code.
self.view.addSubview(customView);
//this will add view to your viewcontroller's view, not in navigationContoller.
You can remove the view,
customView.removeFromSuperview()