Programmatically Add the "+" Button to a UIToolbar - swift

I have been having some trouble with adding a "+" button to a UIToolbar programmatically. Here is my code:
self.tableView.editing = false
var toolbar: UIToolbar = UIToolbar()
toolbar.frame = CGRectMake(0, 0, self.view.frame.size.width, 44)
toolbar.items = [self.editButtonItem()]
self.view.addSubview(toolbar)
I'd like to add something like
self.addButtonItem()
to the array with
self.editButtonItem()
. Sadly, I do not know the syntax and I cannot find it anywhere.
Any response is greatly appreciated!

Add:
UIBarButtonItem(barButtonSustemItem: UIBarButtonSystemItem.Add, target: self, action: Selector("addFunction'sName"))
To the array

Related

UITapGestureRecognizer works first time, but not second time

[Greatly simplified]
I'm following a "Let's Build That App" YouTube series on Firebase 3. It's from 2016, so I've had to rework some of the code since Swift has evolved since then, but mostly it's a useful tutorial.
But, I'm stuck on something.
The red box is intended to be a custom titleView with an Image and Name, but I've simplified it to try to find the problem.
viewWillAppear calls setupNavbar which sets up the navbar.titleView:
func setupNavbar() {
let titleView = UIView()
titleView.frame = CGRect(x: 0, y: 0, width: 300, height: 40)
titleView.backgroundColor = .red
let containerView = UIView() // for the Image and Label, later
containerView.translatesAutoresizingMaskIntoConstraints = false
containerView.backgroundColor = .green
// left, top, width, height anchors equal to same for titleView
containerView.leftAnchor.constraint(equalTo: titleView.leftAnchor)
// top, width, height are similar
titleView.addSubview(containerView)
self.navigationItem.titleView = titleView
let recognizer = UITapGestureRecognizer(target: self, action: #selector(showChatController))
titleView.addGestureRecognizer(recognizer)
}
The selector's function is:
#objc func showChatController() {
let chatController = ChatLogTableViewController()
navigationController?.pushViewController(chatController, animated: true)
}
The class ChatLogTableViewController has just the default viewDidLoad().
First, I'm surprised the box is red, and not green. Why is that?
Second, if I click the red box, the ChatController is loaded, as expected. But, when I click "Back" and return to this screen, the red box is not visible, thus I can no longer tap on it. BUT....If I sign out and sign in/up again, the box is red and I can click it again.
What am I missing?
Update 1: The "+" creates a new controller and presents it.
present(UINavigationController(
rootViewController: NewMessageTableViewController()),
animated: true,
completion: nil)
That controller is currently empty, except for a leftBarButtonItem which is just a barButtonSystemItem (.cancel). Just like "Sign Out", this also "resets" the gesture and it works.
Update 2: Code added upon request.
Update 3: question greatly simplified. Also, if I change the showChatController code to just print ("show Chat Controller"), I can click to my heart's content; the red box and its tap gesture both remain.
So, there is something happening when I ...pushViewController and then come back.
Have you tried to set isUserInteractionEnabled property of the label which you set as the navBar's titleView? I know it's silly but I've missed this a lot of times :)
let recognizer = UITapGestureRecognizer(target: self, action: #selector(YourViewController.titleWasTapped))
titleView.isUserInteractionEnabled = true
titleView.addGestureRecognizer(recognizer)
you can try following things:
1. "User Interaction Enabled" in the UILabel Attributes Inspector in the Storyboard.
2. override func viewDidLoad(animated: Bool) {
super.viewDidAppear(animated)
self.titleView.userInteractionEnabled = true
var tapGesture = titleView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(showChatController)))
self.titleView.addGestureRecognizer(tapGesture)
}
func showChatController() {
println("Tap Gesture recognized")
}
Hi #Zonker I've tested your setupNavBar(). It's working fine nothing worng with your code when I press and go back clicking titleView. Reason why you're not getting .green color is you have to give height and width for containerView and big reason is you've put addSubView code below the anchor and there is no .isActive = true in your containerView.leftAnchor.constraint... Please check setupNavBar() code below:
func setupNavbar() {
let titleView = UIView()
titleView.frame = CGRect(x: 0, y: 0, width: 300, height: 40)
titleView.backgroundColor = .red
let containerView = UIView() // for the Image and Label, later
containerView.translatesAutoresizingMaskIntoConstraints = false
containerView.backgroundColor = .green
titleView.addSubview(containerView)
// left, top, width, height anchors equal to same for titleView
containerView.widthAnchor.constraint(equalToConstant: 300).isActive = true
containerView.heightAnchor.constraint(equalToConstant: 40).isActive = true
containerView.leftAnchor.constraint(equalTo: titleView.leftAnchor).isActive = true
// top, width, height are similar
self.navigationItem.titleView = titleView
let recognizer = UITapGestureRecognizer(target: self, action: #selector(showChatController))
titleView.addGestureRecognizer(recognizer)
}
It would better if you push your code in github so we can test your code

Custom UIButton as Navigation Item Back Button working, but does not show

let btnName = UIButton()
btnName.setImage(UIImage(named: "backIcon"), for: .normal)
btnName.addTarget(self, action: #selector(AddContactViewController.backAction), for: .touchUpInside)
let leftBarButton = UIBarButtonItem()
leftBarButton.customView = btnName
self.navigationItem.leftBarButtonItem = leftBarButton
It works fine, it does what is intended to do. However, on the navigation item it's invisible. But when I click on the area where it should be. It works.
Actually you may have two navigation bars one is of your current class and another is of your previous class.So, you can try by adding below code in your previous class.
override func viewWillDisappear(_ animated: Bool) {
self.navigationController!.navigationBar.isHidden = true
}
I also faced the same problem and it worked for me. May be it will help you.
Everything is ok, except you forgot to set the frame for your button, that's why it's not being shown.
let btnName = UIButton(frame: CGRect(x: 0, y: 0, width: 18, height: 17))
btnName.setImage(UIImage(named: "backIcon"), for: .normal)
btnName.addTarget(self, action: #selector(AddContactViewController.backAction), for: .touchUpInside)
let leftBarButton = UIBarButtonItem()
leftBarButton.customView = btnName
self.navigationItem.leftBarButtonItem = leftBarButton
Rather than hard-coding some frame values, you are better off calling the sizeToFit() method after setting the image, title, etc. I hit this problem today where a custom back button was showing OK on iOS11, but was not visible on iOS9.
btnName.sizeToFit()

Modifying spacing between two right UIBarButtonItems

I want to place two UIBarButtonItems on the right side of my navigation bar. The main problem I'm facing is the spacing between the buttons (the spacing between the right most button and the border of the navigation view has been solved thanks to this post). This is the code I'm using
// add buttons
let buttonEdit: UIButton = UIButton.buttonWithType(UIButtonType.Custom) as UIButton
buttonEdit.frame = CGRectMake(0, 0, 40, 40)
buttonEdit.setImage(UIImage(named:"iconMap"), forState: UIControlState.Normal)
buttonEdit.addTarget(self, action: "rightNavItemEditClick:", forControlEvents: UIControlEvents.TouchUpInside)
var rightBarButtonItemEdit: UIBarButtonItem = UIBarButtonItem(customView: buttonEdit)
let buttonDelete: UIButton = UIButton.buttonWithType(UIButtonType.Custom) as UIButton
buttonDelete.frame = CGRectMake(0, 0, 40, 40)
buttonDelete.setImage(UIImage(named:"iconMap"), forState: UIControlState.Normal)
buttonDelete.addTarget(self, action: "rightNavItemDeleteClick:", forControlEvents: UIControlEvents.TouchUpInside)
var rightBarButtonItemDelete: UIBarButtonItem = UIBarButtonItem(customView: buttonDelete)
let spaceFix: UIBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FixedSpace, target: nil, action: nil)
spaceFix.width = -10
// add multiple right bar button items
self.navigationItem.setRightBarButtonItems([spaceFix,rightBarButtonItemDelete,rightBarButtonItemEdit], animated: true)
If I try to place an additional spacer between the two button (like shown here) there is no apparent effect. I need to get the buttons a bit closer, how can I do that?
You don't really get any control over the spacing between UIBarButtonItems. You can change a UIBarButtonItem's width, but that's all. A UIButtonItem is not a UIView; it has no frame, so you can't say anything about its position. If you want finer control over the look of the interface, you'll have to use a UIBarButtonItem which itself consists of a custom view (init(customView:)). Now you're in the UIView world and you can set the frames of its subviews, which can be real buttons or whatever.

Swift Navigation Bar Button and Title don't appear

I'd like to create a Navigation bar on top of my App. I created an Navigation Controller -> Tab Bar Controller -> Navigation Controller -> Table Controller
I dragged a Bar Button Item on the upper right side.
I double clicked the title in the middle of the Table Controller and wrote a text.
I also tried it with this code in the viewDidLoad() of my controller:
self.navigationController.navigationBar.topItem.title = "some title"
self.navigationItem.setRightBarButtonItem(UIBarButtonItem(barButtonSystemItem: .Search, target: self, action: "barButtonItemClicked:"), animated: true)
self.navigationItem.title = "YourTitle"
Non of it worked - what am I doing wrong? :/
You can try something like this:
self.title = "Your Title"
var homeButton : UIBarButtonItem = UIBarButtonItem(title: "LeftButtonTitle", style: UIBarButtonItemStyle.Plain, target: self, action: "")
var logButton : UIBarButtonItem = UIBarButtonItem(title: "RigthButtonTitle", style: UIBarButtonItemStyle.Plain, target: self, action: "")
self.navigationItem.leftBarButtonItem = homeButton
self.navigationItem.rightBarButtonItem = logButton
I believe you are looking for a titleView.
Try:
var navBarTitleView = UIView(frame: CGRectMake(0.0, 0.0, self.view.frame.width, 44.0))
navBarTitleView.backgroundColor = UIColor.brownColor()
self.navigationItem.titleView = navBarTitleView
I am pretty sure that you can just set the title of your table controller, in its viewDidLoad, which is the title displayed in your navigation bar.
this answer explains a slightly different question, but the concept is the same:
https://stackoverflow.com/a/25167491/2070902
if you want to set your "UINavigationBar" according to your wish Please follow this very safely ,its so simple in swift language ,hope it will help you a lot .
STEP 1:-
Create a category class in swift just go on "New file" and add "Simple swift class " and given it name "MyCustomNavBarCategory.swift"
STEP 2:-
Just "Clean the class (remove all code from this class)" and "Paste my give code below" :-
//class will Start from below line start copy from here
let SCREEN_HEIGHT = UIScreen.mainScreen().bounds.size.height
import UIKit
extension UINavigationBar {
//First increase navigation bar height .
override public func sizeThatFits(size: CGSize) -> CGSize {
NSLog("%f", SCREEN_HEIGHT*0.06);
let newSize:CGSize = CGSizeMake(self.frame.size.width, SCREEN_HEIGHT*0.10)
return newSize;
}
//then set layOut of your Custom Nav for several objects like titleview,buttons and all
public override func layoutSubviews() {
for var view in self.subviews
{
NSLog("view %#", view);
let str :String = view.classForCoder.description();
if(str == "UILabel")
{
//play with title view frame
var f = view.frame;
f.origin.y = self.frame.size.height/2 - view.bounds.size.height/2 ;
view.frame = f;
view.backgroundColor = UIColor.greenColor();
}
else if(str == "UIButton")
{
//play with buttons of navigation bar view frame
var f = view.frame;
f.origin.y = (self.frame.size.height/2) - (view.bounds.size.height/2) ;
view.frame = f;
view.backgroundColor = UIColor.greenColor();
}
}
}
}
//class will end on above stop copy code on above line and just past this in to your "MyCustomNavBarCategory.swift". that's it enjoy ;).
STEP 3:-
Now you can set any frame to any object of UINavigationBar in this class "It's very powerful category of UINavigationBar if you will implement it carefuly".

How to prevent side area clickable of UIBarButtonItem?

`
Whenever i click on this area , action also perform on this.
Don't worry about this behavior, iOS auto tapp near element if there is not other element.
If you really want to prevent to click except button, then you have to put Element on unused area which should be inherited from UIControl or able to get UserInteraction.
I got solution. I put one UIButton between these two UIBarButtonItem and make it custom and nil it's selector.
Also, you can try this: (Swift version)
let btnName = UIButton()
btnName.setImage(UIImage(named: "settings_filled_25"), forState: .Normal)
btnName.frame = CGRectMake(0, 0, 30, 30)
btnName.addTarget(self, action: Selector("toggleRight"), forControlEvents: .TouchUpInside)
var rightView = UIView()
rightView.frame = CGRectMake(0, 0, 30, 30)
rightView.addSubview(btnName)
let rightBarButton = UIBarButtonItem()
rightBarButton.customView = rightView
self.navigationItem.rightBarButtonItem = rightBarButton