How can I add UIToolbar to UIPickerView without using UITextField? - swift

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)

Related

UItoolbar as UITextField inputAccessoryView barButton items out of the safe area in landscape mode

adding a UIToolBar to an UItextField.inputAccessoryView in iOS 16 in landscape mode make the buttons on the right and left be outside the safe area adjusting to superViewEdges instead to safeArealayout.
let doneToolBar = UIToolbar()
let doneBtn = UIBarButtonItem(title: "Done",
style: .plain,
target: self,
action: #selector(self.dismissMyKeyboard))
let upBttn = UIBarButtonItem(image: UIImage(systemName: "chevron.up"),
style: .plain,
target: self,
action: #selector(upAction))
let downBttn = UIBarButtonItem(image: UIImage(systemName: "chevron.down"),
style: .plain,
target: self, action: #selector(downAction))
let flexSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let label = UILabel(frame: CGRect(x: 0,
y: 0,
width: self.view.frame.size.width / 3,
height: self.view.frame.size.height))
label.font = UIFont(name: "Helvetica", size: 13)
label.backgroundColor = UIColor.clear
label.textColor = UIColor.hexStringToUIColor(hex: viewModel.action.primaryColor)
label.text = "Select an expiration date"
label.textAlignment = NSTextAlignment.center
let textBtn = UIBarButtonItem(customView: label)
doneToolBar.items = [upBttn, downBttn, flexSpace, textBtn, flexSpace, doneBtn, flexSpace]
doneToolBar.sizeToFit()
doneToolBar.autoresizingMask = [.flexibleLeftMargin, .flexibleRightMargin ]
doneToolBar.tintColor = UIColor.hexStringToUIColor(hex: viewModel.action.primaryColor)
cardExpTextField.inputAccessoryView = doneToolBar
the code to set the toolbar. and this is the result
tried in iPhone X with iOS 16.1 and simulator. but in simulator with iOS 15.5 work perfect
after rotate to portrait and going back to landscape the button fix the safe are perfect

Do I need to add constraints to my UIToolBar if I'm adding it as a subview to my UIPickerView?

I'm trying to add a simple "Done" button to my UIPickerView programmatically, without using storyboards.
When I try to add toolBar as a subview of the UIPickerView, the toolbar doesn't even show up and I get some constraint related errors.
Any idea on how I can add the button to the PickerView?
Here is a snippet of my code:
var timerImage = UIButton()
var timer = Timer()
var timerDisplayed = 0
let image1 = UIImage(named: "stopwatch")
let timePicker = UIPickerView()
let timeSelect : [String] = ["300","240","180","120","90","60","45","30","15"]
let toolBar = UIToolbar()
let doneButton = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(ThirdViewController.dismissKeyboard))
func pickerViewConstraints(){
timePicker.anchor(top: nil, leading: view.safeAreaLayoutGuide.leadingAnchor, bottom: view.safeAreaLayoutGuide.bottomAnchor, trailing: view.safeAreaLayoutGuide.trailingAnchor)
}
#objc func timeClock(){
toolBar.setItems([doneButton], animated: true)
toolBar.sizeToFit()
toolBar.isTranslucent = false
toolBar.isUserInteractionEnabled = true
toolBar.barStyle = .default
view.addSubview(timePicker)
timePicker.addSubview(toolBar)
pickerViewConstraints()
timePicker.backgroundColor = .white
DispatchQueue.main.async {
self.timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(self.Action), userInfo: nil, repeats: true)
self.timerImage.setImage(nil, for: .normal)
}
}
No, you don't need to add constraints. It can be like :
let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let doneButton = UIBarButtonItem(title: buttonTitle, style: .done, target: self, action: #selector(doneButtonAction))
let cancelButton = UIBarButtonItem(title: cancelTitle, style: .plain, target: self, action: #selector(cancelButtonAction))
let barAccessory = UIToolbar(frame: CGRect(x: 0, y: 0, width: view.frame.width, height: 44))
barAccessory.barStyle = .default
barAccessory.isTranslucent = true
barAccessory.barTintColor = .blue
barAccessory.setItems([cancelButton, space, doneButton], animated: false)
picker.addSubview(barAccessory)
self.view.bringSubviewToFront(picker)
Hope it helps...
You need to set a delegate of type UIPickerViewDelegate to your picker view. In this delegate, implement the delegate method pickerView:viewForRow:forComponent:reusingView
to provide your custom view for the picker item.
For the custom view you provide, you can design it however you want, including adding the button.
It looks like it's just a few minor issues here. Here's how I've done it prior:
override func viewDidLoad() {
super.viewDidLoad()
createToolbar()
}
// Toolbar for "done"
func createToolbar() {
let toolBar = UIToolbar()
toolBar.sizeToFit()
let doneButton = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(PageOneViewController.dismissKeyboard))
toolBar.setItems([doneButton], animated: false)
toolBar.isUserInteractionEnabled = true
// Makes toolbar apply to text fields
educationText.inputAccessoryView = toolBar
politicalText.inputAccessoryView = toolBar
drinkingText.inputAccessoryView = toolBar
heightText.inputAccessoryView = toolBar
schoolInput.inputAccessoryView = toolBar
}
#objc func dismissKeyboard() {
view.endEditing(true)
}
It seems like you haven't technically "called" the toolbar / done button, unless I'm just not seeing that part of the code. Also I've nested the "done" code inside of the function.
If you're using text fields then you should be able to follow to "educationText.inputAccessoryView = toolBar" format to apply all of the code above to each text field (education, politics, drinking, etc). I hope this helps! Good luck.

How to make a toolbar be attached to bottom iOS Swift

I have a ploblem with tab bar and navigation bar. There's a toolbar I need to display on top of the tabbar, but attached to the very bottom.
For now I'm getting this:
My code is:
private func showToolBar() {
tabBarController?.tabBar.isHidden = true
navigationController?.setToolbarHidden(false, animated: true)
let archiveButton = UIBarButtonItem(image: #imageLiteral(resourceName: "deactivateIcons"), style: .plain, target: self, action: #selector(archive))
let flexibleSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: self, action: nil)
let refreshButton = UIBarButtonItem(image: #imageLiteral(resourceName: "changeStatusIcons"), style: .plain, target: self, action: #selector(refresh))
archiveButton.tintColor = Colors.Purple
refreshButton.tintColor = Colors.Purple
setToolbarItems([archiveButton, flexibleSpace, refreshButton], animated: true)
navigationController?.toolbar.setShadowImage(UIImage(), forToolbarPosition: .bottom)
}
So the toolbar appears exactly on top of the tabbar. How to solve this? Thanks in advance!
Try this:
put that code in the last line of your showToolBar() function
let screenSize: CGRect = UIScreen.main.bounds
navigationController?.toolbar.frame = CGRect(x: 0, y: screenSize.height - tabBarHeight - 50, width: screenSize.width, height: 50)

Done Toolbar on UIPickerView

So I have a button on a page when clicked I am opening up a picker view. I have populated the picker view with the months. I added a toolbar but whenever I try to select it just scrolls the picker view to the top.
monthPicker = UIPickerView(frame: CGRect(x: 0, y: self.view.frame.size.height- monthPicker.frame.size.height, width: self.view.frame.size.width, height: monthPicker.frame.size.height))
monthPicker.delegate = self
monthPicker.dataSource = self
monthpickerData = ["January","February","March","April","May","June","July","August","September","October","November","December"]
monthPicker.backgroundColor = UIColor.white
//
let btnDone = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(self.monthdoneButtonAction))
let barAccessory = UIToolbar(frame: CGRect(x: 0, y: 0, width: monthPicker.frame.size.width, height: 44))
barAccessory.barStyle = .default
barAccessory.isTranslucent = false
barAccessory.items = [flexiblespace,btnDone]
monthPicker.addSubview(barAccessory)
It seems like UIPickerView is not letting its children receive touch events. If you are showing this in conjunction with UITextField you can use it's inputView and inputAccessoryView to acheive the same. Alternatively 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)

Change UIBarButtonItem's button title in inputAccessoryView of UITextView after created?

I've created a inputAccessoryView for UITextView in viewDidLoad:
var keyBoardToolBar: UIToolbar = UIToolbar(frame: CGRectMake(0, 0, self.view.frame.size.width, 50))
keyBoardToolBar.barStyle = UIBarStyle.Default
var firstButton: UIBarButtonItem = UIBarButtonItem(title: "firstButton", style: UIBarButtonItemStyle.Plain, target: self, action: Selector("firstButtonAction"))
var flexSpace = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: nil, action: nil)
var done: UIBarButtonItem = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.Done, target: self, action: Selector("doneButtonAction"))
var items = NSMutableArray()
items.addObject(firstButton)
items.addObject(flexSpace)
items.addObject(done)
keyBoardToolBar.items = items as [AnyObject]
keyBoardToolBar.sizeToFit()
self.tv.inputAccessoryView = keyBoardToolBar
And I want to change the firstButton's button text in other function (after viewDidLoad). So how can I do? Thanks!
I var the firstButton: UIBarButtonItem just inside the class before viewDidLoad and change it's title use firstButton.title. :)