Space issue with UIBarButtonItem - ios

I am trying to add a Cancel UIBarButtonItem to my navigation bar using following code:
func setupNavBar() {
self.navBar = UINavigationBar(frame: CGRectMake(0.0, 0.0, UIScreen.mainScreen().bounds.width, 64.0))
let customNavigationItem = UINavigationItem(title: "Connect Accounts")
let cancelButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Cancel, target: self, action: "cancelClicked")
customNavigationItem.setLeftBarButtonItem(cancelButton, animated: true)
self.navBar.setItems([customNavigationItem], animated: true)
self.view.addSubview(self.navBar)
}
The bar button is appearing completely sticked to the screen edge as follow:
Why is this button appearing sticked to the edge of screen and how can I give it spacing so that it does not sticks there? Please help!
EDIT: My button is sticked to just left edge of screen and not to the top-left corner.

The correct way to add space is using .FixedSpace :
let fixedSpace = UIBarButtonItem(barButtonSystemItem: .FixedSpace, target: nil, action: nil)
fixedSpace.width = 10
customNavigationItem.leftBarButtonItems = [fixedSpace, cancelButton]
UIBarButtonSystemItemFixedSpace
Blank space to add between other
items. Only the width property is used when this value is set.
Available in iOS 2.0 and later.

Try this
let btn = UIButton(frame: CGRectMake(<your margin>, 0, 50, 44))
btn.setTitle("Cancel", forState: UIControlStateNormal)
let btnbarButton = UIBarButtonItem(customView: btn)
customNavigationItem.setLeftBarButtonItem(btnbarButton, animated: true)

Try it.
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.setupNavBar()
}
func setupNavBar() {
let navBar = UINavigationBar(frame: CGRectMake(0.0, 0.0, UIScreen.mainScreen().bounds.width, 64.0))
let customNavigationItem = UINavigationItem(title: "Connect Accounts")
let cancelButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Cancel, target: self, action: "cancelClicked:")
let fixedSpace = UIBarButtonItem(barButtonSystemItem: .FixedSpace, target: nil, action: nil)
fixedSpace.width = 10
customNavigationItem.leftBarButtonItems = [fixedSpace, cancelButton]
navBar.setItems([customNavigationItem], animated: true)
self.view.addSubview(navBar)
}
func cancelClicked(sender: AnyObject){
print("Good luck!")
}

Related

Keyboard (numpad) toolbar working but not showing

I tried to add a toolbar for my UITextFiled, the keyboard is set to numpad. It is working but the button is not showing. I created an extension for my UITextfield
extension UITextField {
/// Adding a done button on the keyboard
func addDoneButtonOnKeyboard() {
let doneToolbar = UIToolbar(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 50))
doneToolbar.barStyle = .default
let flexSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let done = UIBarButtonItem(title: "Done", style: .done, target: self, action: #selector(self.doneButtonAction))
let items = [flexSpace, done]
doneToolbar.items = items
doneToolbar.sizeToFit()
self.inputAccessoryView = doneToolbar
}
/// Done button callback
#objc func doneButtonAction() {
self.resignFirstResponder()
}
}
and then I am calling this extension like this
private lazy var fromInputField: CoinpassInput = {
let input = CoinpassInput()
input.keyboardType = .decimalPad
input.addTarget(self, action: #selector(fromInputFieldDidChange), for: .editingChanged)
input.addDoneButtonOnKeyboard()
return input
}()
the toolbar is showing and working but the 'done; button is not showing. If I click on the right corner of the toolbar. the keyboard will hide. I dont know what I am missing why the button is not showing.
Try this code, with slight modifications:
func addDoneButtonOnKeyboard() {
let doneToolbar = UIToolbar(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 50))
doneToolbar.barStyle = .default
doneToolbar.barTintColor = .red
let flexSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let done = UIBarButtonItem(title: "Done", style: .done, target: self, action: #selector(self.doneButtonAction))
done.tintColor = .yellow
doneToolbar.setItems([flexSpace,done], animated: false)
doneToolbar.isUserInteractionEnabled = true
self.inputAccessoryView = doneToolbar
}

iOS toolbar barbuttonitem spacer

I am trying to add two bar buttons to toolbar in iOS [Cancel] & [Save] on right and left side accordingly.
I used a third bar button [Spacer] and set it to be [.flexiblewidth] Otherwise, when adding it only the left button appears [Cancel] and the [Spacer] & and [Save] which have to be next disappearing ?
the screen shot is in the link:
https://ibb.co/cZsaVV
let pickerView = UIPickerView()
override func viewDidLoad() {
pickerView.addSubview(self.setToolBar())
}
func setToolBar() -> UIToolbar {
let toolBar = UIToolbar()
toolBar.isTranslucent = true
toolBar.backgroundColor = UIColor.clear
let barButtonAttr = [NSAttributedString.Key.font : UIFont.systemFont(ofSize: 15),
NSAttributedString.Key.foregroundColor : UIColor.black]
// [Save] BarButtonItem
let saveBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.save, target: self, action: nil)
saveBarButtonItem.setTitleTextAttributes(barButtonAttr, for: .normal)
// [Cancel] BarButtonItem
let cancelBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.cancel, target: self, action: nil)
cancelBarButtonItem.setTitleTextAttributes(barButtonAttr, for: .normal)
let spacerBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.flexibleSpace ,
target: self, action: nil)
spacerBarButtonItem.setTitleTextAttributes(barButtonAttr, for: .normal)
// add BarButtonItems to toolBar
toolBar.items = [cancelBarButtonItem,spacerBarButtonItem,saveBarButtonItem]
toolBar.sizeToFit()
return toolBar
}
func createAccessoryViewWithTarget(_ target: AnyObject, width: CGFloat) -> UIView {
// Previous button
let previousButton = UIBarButtonItem(title: "Previous", style: .plain, target: target, action: #selector(self.moveToPreviousTextField))
previousButton.tintColor = UIColor.white
//Next button
let nextButton = UIBarButtonItem(title: "Next", style: .plain, target: target, action: #selector(self.moveToNextTextField))
nextButton.tintColor = UIColor.white
// Dismiss/close/done button
let doneButton = UIBarButtonItem(title: "Done", style: .done, target: target, action: #selector(self.keyboardDoneButtonTapped))
doneButton.tintColor = UIColor.white
let keyboardToolbar: UIToolbar = UIToolbar(frame: CGRect(x: 0, y: 0, width: width, height: 44))
keyboardToolbar.barStyle = .black
let flexSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let fixedSpace = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil)
var itemsArray = [UIBarButtonItem]()
itemsArray.append(previousButton)
itemsArray.append(fixedSpace)
itemsArray.append(nextButton)
itemsArray.append(flexSpace)
itemsArray.append(doneButton)
keyboardToolbar.items = itemsArray
keyboardToolbar.sizeToFit()
return keyboardToolbar
}
This one is old code may be swift3 I guess. Here Im adding 3 buttons previous next and done button. flexible space and fixed space are used for spaces between buttons. Important to note here is the order that you adding your barbutton items. In your case use flexible space to place your 2 buttons on right and left end in the order of left end button, flexible space, right end button.
I've got the solution finally.
I am adding the ToolBar to the PickerView and then calling UIToolBar.SizeToFit() which is must in all cases.
the issue was I had to change the picker view size later in this case the size of subview ToolBar is not adapting with the new size coordination of pickerView. So the solution simply to call again ToolBar.SizeToFit() after any modification of parent view. here's snap of the code:
// popupView is custom UIPickerView
popupView.frame = CGRect(x:0, y:0, width:100, height:100)
// toolBar is an object of UIToolBar of the custom UIPickerView AddCurrencyPicker
(popupView as! AddCurrencyPicker).toolBar.sizeToFit()

UINavigationItem not displaying left and right barButtons

I'm testing my app on an iPhone 6+. I have a navigation bar which includes two labels, a left bar button (not shown initially), and a right bar button. The problem is that the labels are shown but no matter how hard I try I can't make it show the buttons. They work(if you tap on where they should be, they work as expected) but are not shown. The tests on an iPhone 5s (physic) and iPhone X (simulator) went correctly and the buttons are shown.
Is there any problem with my code?
Thank you.
override func viewDidLoad() {
super.viewDidLoad()
webView.delegate = self
loadWeb()
let button = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.action, target: self, action: #selector(share))
button.tintColor = UIColor.white
self.navigationItem.rightBarButtonItem = button
let frameLabelURLTitle = CGRect.init(x: 25, y: 2, width: (self.navigationController?.navigationBar.frame.size.width)! - 182, height: (self.navigationController?.navigationBar.frame.size.height)! - 20)
let frameLabelURL = CGRect.init(x: 25, y: 2 + frameLabelURLTitle.height, width: (self.navigationController?.navigationBar.frame.size.width)! - 182, height: 10)
let viewLabel = UIView.init(frame: frameLabelURLTitle)
labelTitleURL = UILabel.init(frame: frameLabelURLTitle)
labelURL = UILabel.init(frame: frameLabelURL)
labelURL.textColor = UIColor.white
labelTitleURL.textColor = UIColor.white
labelURL.font = UIFont.systemFont(ofSize: 13.0)
viewLabel.addSubview(labelTitleURL)
viewLabel.addSubview(labelURL)
self.navigationController?.navigationBar.addSubview(viewLabel)
loadingLabel.text = "loadingWeb".localized()
loadingLabel.sizeToFit()
self.navigationController?.isNavigationBarHidden = true
self.placeHolderView.layer.insertSublayer(initGradient(bounds: self.view.bounds, isHorizontal: false), at: 0)
self.loadingGifImageView.image = UIImage.gif(asset: "01-GIF_LOGO")
}
func webViewDidFinishLoad(_ webView: UIWebView) {
self.placeHolderView.isHidden = true
self.navigationController?.isNavigationBarHidden = false
labelTitleURL.text = webView.stringByEvaluatingJavaScript(from: "document.title")
labelURL.text = webView.request?.url?.absoluteString.components(separatedBy: "/")[2]
self.navigationItem.leftBarButtonItem = nil
if !(webView.request?.url?.absoluteString.contains("/blog/"))! {
let newBackButton = UIBarButtonItem(image: UIImage(named: "bt_close")?.withRenderingMode(.alwaysOriginal), style: UIBarButtonItemStyle.plain, target: self, action: #selector(back))
newBackButton.isEnabled = true
print(newBackButton.style)
self.navigationItem.setLeftBarButton(newBackButton, animated: true)
self.navigationItem.leftBarButtonItem = newBackButton
self.navigationItem.backBarButtonItem = newBackButton
}
}

BarButtonItem EdgeInsets doesn't work

I'm trying to add a padding to the right of a navigationBar rightBarButtonItems in between the buttons but it's now working.
Here's the button creation code with the given inset:
lazy var previewBarButtonItem: UIBarButtonItem = {
let buttonItem = UIBarButtonItem(title: "Preview", style: .plain, target: self, action: #selector(handlePreview))
buttonItem.tintColor = UIColor.black
buttonItem.setTitleTextAttributes([NSFontAttributeName: UIFont.systemFont(ofSize: 14)], for: .normal)
buttonItem.imageInsets = UIEdgeInsetsMake(0, -15, 0, 15)
return buttonItem
}()
override func viewDidLoad() {
super.viewDidLoad()
setupRightNavItems()
}
fileprivate func setupRightNavItems () {
navigationItem.rightBarButtonItems = [submitBarButtonItem, previewBarButtonItem]
}
Can you give a hint on why this isn't working?
Thanks
I managed to fix this issue, just added a fixedSpace in-between the bar button items as follows:
1) remove any EdgeInsets
2) add the following fixed space:
fileprivate func setupRightNavItems () {
let spacing = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil)
spacing.width = 25 //change to your desired space width
navigationItem.rightBarButtonItems = [submitBarButtonItem, spacing, previewBarButtonItem]
}

How to add done button on keyboard on top of keyboard in IOS?

I want to add the Done button on the top of keyboard on right side in iOS for a textView.Please tell me how can i do that?
I want to achieve something similar to the above keyboard
Hope this help :)
UIToolbar* keyboardToolbar = [[UIToolbar alloc] init];
[keyboardToolbar sizeToFit];
UIBarButtonItem *flexBarButton = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
target:nil action:nil];
UIBarButtonItem *doneBarButton = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemDone
target:self action:#selector(yourTextViewDoneButtonPressed)];
keyboardToolbar.items = #[flexBarButton, doneBarButton];
self.yourTextView.inputAccessoryView = keyboardToolbar;
and then add yourTextViewDoneButtonPressed method
-(void)yourTextViewDoneButtonPressed
{
[self.yourTextView resignFirstResponder];
}
It can be done using storyboard:
Add UITextField to UIViewController view.
Add UIToolbar in the first level of UIViewController
Add UIBarButtonItem into the UIToolbar.
Connect UItoolbar to the code using IBOutlet.
Connect UIBarButtonItem to the code using IBAction (as didClick).
Make the UITextField will be delegating to UIViewController.
In the didClick function end editing (view.endEditing(true))
In the delegate function textFieldShouldBeginEditing should be: textField.inputAccessoryView = toolbar and returns true.
Swift 3:
func setDoneOnKeyboard() {
let keyboardToolbar = UIToolbar()
keyboardToolbar.sizeToFit()
let flexBarButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let doneBarButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(InsertStatusVC.dismissKeyboard))
keyboardToolbar.items = [flexBarButton, doneBarButton]
self.fullNameTextField.inputAccessoryView = keyboardToolbar
}
#objc func dismissKeyboard() {
view.endEditing(true)
}
This Solution For Swift3+
Add This line To your Project As a extension
Your Problem is solved.
extension UITextField{
#IBInspectable var doneAccessory: Bool{
get{
return self.doneAccessory
}
set (hasDone) {
if hasDone{
addDoneButtonOnKeyboard()
}
}
}
func addDoneButtonOnKeyboard()
{
let doneToolbar: UIToolbar = UIToolbar(frame: CGRect.init(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 50))
doneToolbar.barStyle = .default
let flexSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let done: UIBarButtonItem = UIBarButtonItem(title: "Done", style: .done, target: self, action: #selector(self.doneButtonAction))
let items = [flexSpace, done]
doneToolbar.items = items
doneToolbar.sizeToFit()
self.inputAccessoryView = doneToolbar
}
#objc func doneButtonAction() {
self.resignFirstResponder()
}
}
Before extension
After extension
Solution for Swift 4 and Swift 5 using a custom class. You can use this class in your Storyboard and .xib files.
class UITextFieldWithDoneButton: UITextField {
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.addDoneButtonOnKeyboard()
}
fileprivate func addDoneButtonOnKeyboard() {
let doneToolbar: UIToolbar = UIToolbar(frame: CGRect.init(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 50))
doneToolbar.barStyle = .default
let flexSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let done: UIBarButtonItem = UIBarButtonItem(title: "Done", style: .done, target: self, action: #selector(self.doneButtonAction))
let items = [flexSpace, done]
doneToolbar.items = items
doneToolbar.sizeToFit()
self.inputAccessoryView = doneToolbar
}
#objc fileprivate func doneButtonAction() {
self.resignFirstResponder()
}
}
This Solution For Swift 4
override func viewDidLoad() {
super.viewDidLoad()
//init toolbar
let toolbar:UIToolbar = UIToolbar(frame: CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 30))
//create left side empty space so that done button set on right side
let flexSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let doneBtn: UIBarButtonItem = UIBarButtonItem(title: “Done”, style: .done, target: self, action: Selector(“doneButtonAction”))
toolbar.setItems([flexSpace, doneBtn], animated: false)
toolbar.sizeToFit()
//setting toolbar as inputAccessoryView
self.textField1.inputAccessoryView = toolbar
self.textField2.inputAccessoryView = toolbar
}
func doneButtonAction() {
self.view.endEditing(true)
}
Add UIToolBar as custom view that will have UIBarButtonItem as Done button in it.
This is safer and cleaner way to add Done button to any Type of Keyboard. Create UIToolBar add Done Button to it and set inputAccessoryView of any UITextField or UITextView.
];
}
SWIFT 3
var ViewForDoneButtonOnKeyboard = UIToolbar()
ViewForDoneButtonOnKeyboard.sizeToFit()
var btnDoneOnKeyboard = UIBarButtonItem(title: "Done", style: .bordered, target: self, action: #selector(self.doneBtnFromKeyboardClicked))
ViewForDoneButtonOnKeyboard.items = [btnDoneOnKeyboard]
myTextField.inputAccessoryView = ViewForDoneButtonOnKeyboard
Function
#IBAction func doneBtnfromKeyboardClicked (sender: Any) {
print("Done Button Clicked.")
//Hide Keyboard by endEditing or Anything you want.
self.view.endEditing(true)
}
The answer from Ramis that allows the keyboard accessory view to be created using the Storyboard is a great strategy. It is 2017 after all! (Sorry, but I do not have enough points to upvote you.)
Let me add a little to the answer (to keep within the SO rules). I have a view with multiple textFields. After implementing each of Ramis' steps I attached the accessoryView to all of the textFields in this way:
-(void)textFieldDidBeginEditing:(UITextField *)textField
{
_activeTextField = textField;
[_activeTextField setInputAccessoryView:_iboKeyboardTools];
}
So easy compared with implementing all this in code! Just build the accessory view in Storyboard- and attach it again and again!

Resources