Swift: Programmatically add UIButton above keyboard - swift

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

Related

Swift UIBarButtonItem add Gesture Recognizer

I want to add a long press Gesture Recognizer to a UIBarButtonItem, but I can't. There is no possibility using the Storyboard, nor is there a method addGestureRecognizer in UIBarButtonItem.
How can I solve this problem?
You can try the following method:
//1. Create A UIButton Which Can Have A Gesture Attached
let button = UIButton(type: .custom)
button.frame = CGRect(x: 0, y: 0, width: 80, height: 40)
button.setTitle("Press Me", for: .normal)
//2. Create The Gesture Recognizer
let longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(doSomething))
longPressGesture.minimumPressDuration = 1
button.addGestureRecognizer(longPressGesture)
//3. Create A UIBarButton Item & Initialize With The UIButton
let barButton = UIBarButtonItem(customView: button)
//4. Add It To The Navigation Bar
self.navigationItem.leftBarButtonItem = barButton
Of course the Selector method would be replaced with your own method.
Didn't work with UIButton (iOS 12), however works with UILabel:
let backButtonView = UILabel()
backButtonView.isUserInteractionEnabled = true
backButtonView.text = "x"
backButtonView.sizeToFit()
backButtonView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(onBackButtonClick(_:))))
backButtonView.addGestureRecognizer(UILongPressGestureRecognizer(target: self, action: #selector(onBackButtonLongPress(_:))))
navigationItem.leftBarButtonItem = UIBarButtonItem(customView: backButtonView)

NavigationBarButton Item Not able to align vertically?

Hi I have tried to align the navigationbar button item position center in the navigation bar. I have changed the navigation bar height programmatically so I have able to align title its working fine, but same I have tried leftbarbutton and rightbarbutton. its has not vertically aligned center. I have tried these programmatically
Title Alignment
self.navigationController!.navigationBar.setTitleVerticalPositionAdjustment(-15, forBarMetrics: .Default)
RightBarButton:
let button: UIButton = UIButton(type: .Custom)
button.setImage(buttonImage, forState: UIControlState.Normal)
button.addTarget(self, action: #selector(self.toggleRight), forControlEvents: UIControlEvents.TouchUpInside)
button.frame = CGRectMake(0, 0, 40, 40)
let rightButton = UIBarButtonItem(customView: button)
// rightButton.imageInsets = UIEdgeInsets(top: 20, left: 0, bottom: 0, right: 0)
let negativeSpacer = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FixedSpace, target: nil, action: nil)
negativeSpacer.width = -10;
self.navigationItem.rightBarButtonItems = [negativeSpacer ,rightButton ]
LeftBarButton:
let button: UIButton = UIButton(type: .Custom)
button.setImage(buttonImage, forState: UIControlState.Normal)
button.addTarget(self, action: #selector(self.toggleLeft), forControlEvents: UIControlEvents.TouchUpInside)
button.frame = CGRectMake(0, 0, 40, 40)
let leftButton = UIBarButtonItem(customView: button)
let negativeSpacer = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FixedSpace, target: nil, action: nil)
negativeSpacer.width = -10;
self.navigationItem.leftBarButtonItems = [negativeSpacer,leftButton ]
Please find the screenshot.

How can I add UIToolbar to UIPickerView without using UITextField?

I have used UIPickerView without UITextField. After user tap on button, UIPickerView will display.
Anyway, I have no idea how to dismiss UIPickerView. I have tried to set inputAccessoryView with UIToolbar but the complier said it's get-only property.
My code:
let toolbar = UIToolbar()
toolbar.barStyle = UIBarStyle.default
toolbar.isTranslucent = true
toolbar.sizeToFit()
let doneButton = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.done, target: self, action: #selector(RegisterViewController.pickerDoneButton))
let spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: self, action: nil)
let cancelButton = UIBarButtonItem(title: "Cancel", style: UIBarButtonItemStyle.plain, target: self, action: #selector(RegisterViewController.pickerCancelButton))
toolbar.setItems([cancelButton, spaceButton, doneButton], animated: true)
toolbar.isUserInteractionEnabled = true
pickerView.inputAccessoryView = toolbar
Error: Cannot assign to property: 'inputAccessoryView' is a get-only property
Try to add subview to the UIPickerView
It seems like UIPickerView is not letting its children receive touch events. If you want to add toolbar to pickerview without textfield you can create a top level container UIView to hold both toolbar and picker view like this:
let picker = UIView(frame: CGRect(x: 0, y: view.frame.height - 260, width: view.frame.width, height: 260))
// Toolbar
let btnDone = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(self.monthdoneButtonAction))
let spaceButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let cancelButton = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(self.cancelClick))
let barAccessory = UIToolbar(frame: CGRect(x: 0, y: 0, width: picker.frame.width, height: 44))
barAccessory.barStyle = .default
barAccessory.isTranslucent = false
barAccessory.items = [cancelButton, spaceButton, btnDone]
picker.addSubview(barAccessory)
// Month UIPIckerView
monthPicker = UIPickerView(frame: CGRect(x: 0, y: barAccessory.frame.height, width: view.frame.width, height: picker.frame.height-barAccessory.frame.height))
monthPicker.delegate = self
monthPicker.dataSource = self
monthpickerData = ["January","February","March","April","May","June","July","August","September","October","November","December"]
monthPicker.backgroundColor = UIColor.white
picker.addSubview(monthPicker)

LeftbarButtonItem remove padding?

I would like to use a logo as LeftbarButtonItem in an UINavigationController, is it possible to remove the left padding here?
Ill alreay tried:
let logoView = UIView(frame: CGRectMake(-15, 0, 44, 44))
logoView.backgroundColor = UIColor.darkGrayColor()
var leftBarButtonItem: UIBarButtonItem = UIBarButtonItem(customView: logoView)
self.navigationItem.setLeftBarButtonItem(leftBarButtonItem, animated: false)
But thats not working. Ill mean that space shown here in this picture:
Any ideas? Thanks in advance.
Here is the Swift Solution:
let logoView = UIView(frame: CGRectMake(0, 0, 44, 44))
logoView.backgroundColor = UIColor.darkGrayColor()
let negativeSpacer = UIBarButtonItem.init(barButtonSystemItem: .FixedSpace, target: nil, action: nil)
negativeSpacer.width = -20;
let leftBarButtonItem: UIBarButtonItem = UIBarButtonItem(customView: logoView)
self.navigationItem.leftBarButtonItems = [negativeSpacer, leftBarButtonItem]
Here's an example of removing the padding to the left of a custom left button item:
UIBarButtonItem *backButtonItem // Assume this exists, filled with our custom view
// Create a negative spacer to go to the left of our custom back button,
// and pull it right to the edge:
UIBarButtonItem *negativeSpacer = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace
target:nil action:nil];
negativeSpacer.width = -5;
// Note: We use 5 above b/c that's how many pixels of padding iOS seems to add
// Add the two buttons together on the left:
self.navigationItem.leftBarButtonItems = [NSArray
arrayWithObjects:negativeSpacer, backButtonItem, nil];
swift version of #Piyush Sharma ' Answer
actionBarWidth = self.navigationController?.navigationBar.frame.width as! CGFloat
actionBarHeight = self.navigationController?.navigationBar.frame.height as! CGFloat
actionBarView.frame = CGRect (x: 0, y: 0, width: actionBarWidth, height: actionBarHeight)
let emptySpace = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil)
emptySpace.width = -16
let leftBarBtn = UIBarButtonItem(customView: actionBarView)
self.navigationItem.leftBarButtonItems = [emptySpace,leftBarBtn]

Back Button Image - what is it called in Swift?

I am trying to use Swift's internal back button image.
I have asked this question before and got the technically correct answer that it inherits it from the previous View, BUT if I insert this code you can control the back button on the current View.
// Takeover Back Button
self.navigationItem.hidesBackButton = false
let newBackButton = UIBarButtonItem(title: "<", style: .Plain, target: self, action: "segueBack")
navigationItem.leftBarButtonItem = newBackButton
That gives me a <, "ABC" would give me ABC etc but how do I trigger Swift to put up it's internal Back Button image. The code below doesn't work but I would have thought is along the right lines.
let backImg: UIImage = UIImage(named: "BACK_BUTTON_DEFAULT_ICON")!
navigationItem.leftBarButtonItem!.setBackgroundImage(backImg, forState: .Normal, barMetrics: .Default)
Has anyone worked out how to do this?
Try to add custom view as back button like as
var backButton = UIButton(frame: CGRectMake(0, 0, 70.0, 70.0))
var backImage = UIImage(named: "backBtn")
backButton.setImage(backImage, forState: UIControlState.Normal)
backButton.titleEdgeInsets = UIEdgeInsetsMake(10.0, 10.0, 10.0, 0.0)
backButton.setTitle("Back", forState: UIControlState.Normal)
backButton.addTarget(self, action: "buttonPressed", forControlEvents: UIControlEvents.TouchUpInside)
var backBarButton = UIBarButtonItem(customView: backButton)
var spacer = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FixedSpace, target: nil, action: nil)
spacer.width = -15
self.navigationItem.leftBarButtonItems = [spacer,backBarButton]
It will look same as iOS back button
I struggled with this question for a while. Finally I got the back image with the following code:
let backImage = navigationController?.navigationBar.subviews[2].subviews[0].subviews[0].subviews[0] as! UIImageView).image
Before run the code above, make sure the back button is showing. Then you can save backImage to anywhere you want.
Here is the backImage I got.
Here is my solution:
override func viewDidLoad() {
...
let buttonBack = UIBarButtonItem(image: UIImage(named: "backButton"), style: .plain, target: self, action: #selector(buttonSavePressed(_:)))
self.navigationItem.leftBarButtonItem = buttonBack
let backButton = UIButton(frame: CGRect(x: 0, y: 0, width: 24.0, height: 24.0))
let backImage = UIImage(named: "backButton")
backButton.setImage(backImage, for: .normal)
backButton.setTitle("Back", for:.normal)
if #available(iOS 13.0, *) {
backButton.setTitleColor(.link, for: .normal)
} else {
backButton.setTitleColor(.blue, for: .normal)
}
backButton.addTarget(self, action:#selector(buttonSavePressed(_:)), for: .touchUpInside)
let backBarButton = UIBarButtonItem(customView: backButton)
let spacer = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil)
spacer.width = -15
self.navigationItem.leftBarButtonItems = [spacer,backBarButton]
}
#objc func buttonBackPressed(_ sender: Any) {
...
}
If you want to get the default back button image, the arrow is a class of type _UINavigationBarBackIndicatorView.
Here follows the hack,
UIImage *imgViewBack ;
for (UIView *view in self.navigationController.navigationBar.subviews) {
// The arrow is a class of type _UINavigationBarBackIndicatorView. This is not any of the private methods, so I think
// this is fine for the AppStore...
if ([NSStringFromClass([view class]) isEqualToString:#"_UINavigationBarBackIndicatorView"]) {
// Set the image from the Default BackBtn Imageview
UIImageView *imgView = (UIImageView *) view;
if(imgView){
imgViewBack = imgView.image ;
}
}
}
Try this to replace the back button image:
let back_image = UIImage(named: "btn_back")
self.navigationBar.backIndicatorImage = back_image
self.navigationBar.backIndicatorTransitionMaskImage = back_image
If you don't like to have the "Back" title you can add this too:
self.navigationBar.topItem?.title = ""