I am adding a UIToolbar to a UIPickerview programatically and I want the toolbar to be positioned directly above the picker view, which is centered in the view controller. I have used the following to center the toolbar, but the toolbar ends up on top of (in front of) my picker view:
self.toolBar.center = self.view.center
I also tried the following, but the toolbar ends up at the top of the view controller:
self.view.addSubview(self.toolBar)
How do I go about solving this positioning issue?
below is the code used to build the toolbar:
self.toolBar.barStyle = UIBarStyle.default
self.toolBar.isTranslucent = true
self.toolBar.tintColor = UIColor.white
self.toolBar.sizeToFit()
// self.toolBar.center = self.view.center
// self.view.addSubview(self.toolBar)
let doneButton = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.done, target: self, action: Selector("donePicker"))
self.toolBar.setItems([doneButton], animated: false)
self.toolBar.isUserInteractionEnabled = true
Set toolbar as an inputAccessoryView of UITextField after setting UIPickerView as inputView for textField like below,
textField.inputView = pickerView
textField.inputAccessoryView = self.toolBar
Remove adding toolBar as a subview
self.view.addSubview(self.toolBar)
Related
I'm a beginner in swift and trying to learn UIPickerView which has done button to close after the selection from the picker view. I have following code to add the tool bar and the done button to the picker as a toolbar in subview. It shows up as a blank black toolbar (attached screenshot)
let toolBar = UIToolbar()
toolBar.barStyle = .black
toolBar.sizeToFit()
let doneBtn = UIBarButtonItem.init(title: "Done", style: .plain, target: self, action: #selector(self.closePicker))
toolBar.items = [doneBtn]
toolBar.isUserInteractionEnabled = true
picker.addSubview(toolBar)
Picker is the outlet for UIPickerView in my controller. What am I doing wrong? I referred to other questions but they dont seem to solve my problem. Any suggestions?
You are wrong at this line:
picker.addSubview(toolBar)
Picker is not supposed to have any subviews - it's a comprehensive view by itself and there is no area in it to accommodate anything in addition.
Instead you need to add both the picker and the toolbar on the same view and align them next to each other
let toolBar = UIToolbar()
...configure your toolbar here...
guard let superview = picker.superview else { return }
superview.addSubview(toolBar)
toolBar.translateAutoresizingMaskIntoConstraints = false
NSLayoutConstraints.activate([
toolBar.topAnchor.constraint(equalTo: superview.topAnchor),
toolBar.leftAnchor.constraint(equalTo: superview.leftAnchor),
toolBar.rightAnchor.constraint(equalTo: superview.rightAnchor),
toolBar.bottomAnchor.constraint(equalTo: picker.topAnchor)
])
You should not add toolBar as subView of picker.
You should set the toolBar as inputAccessoryView of textField.
As I searched for this problem I got that the common way (also easiest way) to achieve what you want is Using dummy textField.
It means create a textField at the exact frame of button and hide it, when user touches the button make the textField firstResponder.
#IBAction func pickerButtonClicked(_ sender: Any) {
self.pickerViewTextField.becomeFirstResponder
}
My app requires me to add multiple buttons in my navigation bar.
Here is an image of what my nav bar looks like
How do i achieve this type of design?
You can configure your view controller's navigationItem in various ways to achieve this design.
Left side
To allow additional buttons next to the system "back button" on the left:
navigationItem.leftItemsSupplementBackButton = true
This allows you to add a left bar button item for the circular image:
navigationItem.setLeftBarButtonItem(imageItem, animated: trueOrFalse)
imageItem would be a UIBarButtonItem initialized with a customView or image, as discussed in some of the other answers here.
For the back button itself, to achieve a simple "<" without showing the title of the previous view or showing "< Back", you can open the storyboard and set the Back Button text of the previous view controller to a single space, as described in this post.
Title area
For the title area, as discussed in the other answers:
navigationItem.titleView = (a custom view)
Right side
For the right side, you can add multiple buttons:
navigationItem.setRightBarButtonItems([button1, button2, button3, button4], animated: trueOrFalse)
Here, button1, button2, button3, and button4 are each UIBarButtonItems. You would likely initialize these buttons with images.
Looks like you also will want to set the tintColor of the navigation bar to black, so that the bar buttons are rendered in black:
navigationController?.navigationBar.tintColor = .black
All of this code would be done in the view controller, usually in viewDidLoad, unless you need to dynamically change which buttons are shown as the content of your view controller changes.
Try this:
let callImage = UIImage(named: "call")!
let videoImage = UIImage(named: "video")!
let searchImage = UIImage(named: "search")!
let callButton = UIBarButtonItem(image: callImage, style: .plain, target: self, action: #selector(didTapCallButton))
let videoButton = UIBarButtonItem(image: searchImage, style: .plain, target: self, action: #selector(didTapVideoButton))
let searchButton = UIBarButtonItem(image: searchImage, style: .plain, target: self, action: #selector(didTapSearchButton))
navigationItem.rightBarButtonItems = [callButton, videoButton, searchButton]
Selector methods
func didTapCallButton(sender: AnyObject){
...
}
func didTapVideoButton(sender: AnyObject){
...
}
func didTapSearchButton(sender: AnyObject){
...
}
You can create your own view and put down your Images, Labels, etc...
After that, you write:
self.navigationItem.titleView = yourView
UINavigationItem has a property called rightBarButtonItems, this expects an array of UIBarButtonItem which would in your case be each of your buttons.
You can use the initialiser on UIBarButtonItem to specify the image and style:
init(image: UIImage?, style: UIBarButtonItemStyle, target: Any?, action: Selector?)
Initializes a new item using the specified image and other properties.
On your view controller you can access the navigation item through the accessor navigationItem, if you embed your view controller inside a UINavigationController you will need to access the navigationItem on that instance and not the view controller.
You can Add UIView in navigation bar so that you can add multiple buttons in that view.
I am having tableview EKEvents, if a user taps on an event i will push EKEventViewController.
EKEventViewController comes default with delete button in toolbar how can I hide this.
I tried making a custom viewController subclass of EKEventViewController and in viewWillAppear i was hiding the navigationController's toolbar it was working but not properly.Another problem with this it will allows me to navigate to event details which is not required.
let eventViewControler = EKEventViewController()
eventViewController.event = self.events[indexPath.row]
eventViewController.allowsEditing = false
self.navigationController.pushViewController(eventViewControler)
How can I hide the only delete button.
You can customize rightBarButtonItem.
let rightButton : UIBarButtonItem = UIBarButtonItem(title: "", style: UIBarButtonItemStyle.Plain, target: self, action: "")
self.navigationItem.rightBarButtonItem = rightButton
I am experiencing an issue with the inputAccessoryView after ANY other view has been rotated. For example:
1) go to view A and rotate to landscape
2) then rotate back to portrait.
3) go to view B
in view B I have the below code to assign an inputAccessoryView to a UITextField However, after I rotate any view in the app, the accessory view always attaches to the top of the screen and not the top of the keyboard. If I don't rotate any view the accessory view attaches to the top of the keyboard as expected.
Here is the code used to create and assign the inputAccessoryView, it is called from the viewDidLoad
func addDoneButtonOnKeyboard(){
let doneToolbar = UIToolbar(frame: CGRect(x:0, y:0, width:320, height:50))
doneToolbar.barStyle = UIBarStyle.blackTranslucent
doneToolbar.isTranslucent = true
let flexSpace = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace,
target: nil,
action: nil)
let doneButton = UIBarButtonItem(title: "Done",
style: UIBarButtonItemStyle.done,
target: self,
action: #selector(MyVC.doneButtonAction))
doneToolbar.setItems([flexSpace,doneButton], animated: false)
doneToolbar.sizeToFit()
doneToolbar.autoresizingMask=UIViewAutoresizing.flexibleWidth
self.myTextFild.inputAccessoryView = doneToolbar
}
I have searched SO but did not see any other questions/answers similar....
I my case the inputView was a datePicker and I had the same problem. The solution for me was:
textFieldDate.inputView?.autoresizingMask = [.flexibleHeight, .flexibleWidth]
Not sure if this helps for you as well, cause you are using a keyboard as inputView but maybe it helps others with datePicker problems.
I use the following code to add a navigation bar with buttons to my view:
let navBar = UINavigationBar(frame: CGRectMake(0, 20, screenWidth, 44))
var homeButton : UIBarButtonItem = UIBarButtonItem(title: "", style: UIBarButtonItemStyle.Bordered, target: controller, action: "closeView")
homeButton.image = UIImage(named: "back.png")
var item = UINavigationItem(title: title)
item.leftBarButtonItem = homeButton
if addPlus {
var addButton : UIBarButtonItem = UIBarButtonItem(title: "", style: UIBarButtonItemStyle.Bordered, target: controller, action: "addItem")
addButton.image = UIImage(named: "plus-25.png")
item.rightBarButtonItems = [addButton]
}
var items = [
item
]
navBar.setItems(items, animated: true)
controller.view.addSubview(navBar)
For some reason when any type of UIAlertView is displayed the buttons on the bar shift down.
Any ideas why this is happening?
In your storyboard, bring a navigation bar and make it to be auto-fitted in the screen, and don't try shifting it down.
Not the best solution, but since this behavior was only happening with my custom bar button items (and not the bar button items I made using interface builder) I just removed them with "self.navBarNavItem.setRightBarButtonItems([], animated: true)" before calling "presentViewController".
Then if the result of the alert (i.e. what the user selected) resulted in staying on the current view (instead of changing views) then I add them back in when that handler is executed.
This stopped the buttons from visibly showing in the wrong position and then put them back in the correct position when the alert completed.