Swift inputAccessoryView not attached to keyboard after rotation - ios

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.

Related

Swift - Toolbar done button not appearing in UIPickerView subview

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
}

iOS 11 extra space between keyboard and accessoryView

I have some weird UI bug with inputAccessoryView and keyboard.
Code to add inputAccessoryView in viewDidLoad
let keyboardToolbar = UIToolbar()
keyboardToolbar.items = [
UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil),
UIBarButtonItem(title: "Hide", style: .done, target: self, action: #selector(resignFirstResponder))
]
keyboardToolbar.barStyle = barStyle
keyboardToolbar.sizeToFit()
myTextfield.inputAccessoryView = keyboardToolbar
First time entering screen and tap to textfield works good.
After closing this screen (popViewController) and entering it again and get focus to textField I've got this:
UIToolBar is above keyboard. Empty space have height = keyboard height
ui bug image
this because there is safe area in IOS 11 and this space appear on iphone X
Check this post may be duplicated
iPhone X how to handle View Controller inputAccessoryView?
I do not know the reason but workaround is to call either
view.endEditing
or
textField.resignFirstResponder()
in
viewWillDisappear

Positioning UIToolbar swift

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)

UIButtonBarItem does not seem to fire selector

I am writing a simple iOS app in XCode 7.3, which I believe puts me using Swift 2.2. I am trying to use a UIDatePicker with UIToolbar with a UITextfield, and for some reason I tapping on the Cancel button seems not to call the method datePickerCancelled on the controller. Everything displays fine(picker, buttons , etc.), but the event won't fire. I have tried several variations of adding the selector to the UIBarButtonItem, and nothing seems to work. As you can see from the code this a pretty trivial case so it escapes why it should be this difficult. Thank you.
override func viewDidLoad() {
super.viewDidLoad()
var datePicker = UIDatePicker()
var datePickerToolbar = UIToolbar()
let doneButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Done, target: nil, action: nil)
let cancelButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Cancel, target: self, action: #selector(datePickerCancelled))
let flexSpace = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: nil, action: nil)
datePickerToolbar.setItems([cancelButton,flexSpace, doneButton], animated: true)
datePicker.userInteractionEnabled = true
cancelButton.enabled = true
self.dateField.inputView = datePicker
self.dateField.inputAccessoryView = datePickerToolbar
}
func datePickerCancelled(){
self.datePicker.resignFirstResponder();
}` I
The problem is this line:
var datePickerToolbar = UIToolbar()
This results in a toolbar of zero size. The Cancel button is visible, but it is outside of its superview, namely the toolbar — because the toolbar has zero size.
A view outside of its superview cannot be tapped.
You can easily confirm this by setting the toolbar's clipsToBounds to true and running the app. The Cancel button will now be invisible, because things outside the toolbar are no longer shown.
If the event did fire, your datePickerCancelled function still wouldn't do anything:
func datePickerCancelled(){
self.datePicker.resignFirstResponder();
}
Your date picker was never first responder, so that line wouldn't cause anything to happen.
Perhaps you meant this:
func datePickerCancelled(){
self.dateField.resignFirstResponder();
}

Reorganizing Toolbar and NavigationBar after TraitCollectionDidChange

I want to support a layout similar to Safari, where in horizontally regular environments, buttons are displayed on the navigation bar, but in horizontally compact environments, some buttons are on the navigation bar and some buttons are on the toolbar.
This is what I have in my traitCollectionDidChange
override func traitCollectionDidChange(previousTraitCollection: UITraitCollection?) {
let editingContextButton = editing ? resetButton : doneButton
if traitCollection.horizontalSizeClass == .Regular {
navigationController?.toolbarHidden = true
navigationItem.leftBarButtonItems = [editButtonItem(), helpButton]
navigationItem.rightBarButtonItems = [editingContextButton, addButton]
} else if traitCollection.horizontalSizeClass == .Compact{
navigationController?. toolbarHidden = false
navigationItem.leftBarButtonItems = [editButtonItem()]
navigationItem.rightBarButtonItems = [editingContextButton]
navigationController?.toolbarItems = [helpButton, UIBarButtonItem(barButtonSystemItem: .FlexibleSpace, target: nil, action: nil), addButton]
}
}
But it seems there is a problem when transitioning from a regular horizontal size class to a compact one. The items in the navigation bar are always correct, but the toolbar items are cut off or empty.
When bringing up the ViewController, it is always set up and displayed correctly, and it's always right in the horizontally regular size class – there's only a problem when the size class changes from regular to compact.
Here's an example, showing the add button in the bottom right disappearing from the toolbar after the change in size class.
The same thing happens when rotating the device on 5.5" iPhones, and in portrait on iPad, the toolbar is just empty after activating multitasking. What's the problem here? Thanks!
I realized that I was not setting the toolbar items correctly. Instead of
navigationController?.toolbarItems = [helpButton, UIBarButtonItem(barButtonSystemItem: .FlexibleSpace, target: nil, action: nil), addButton]
I should have done:
setToolbarItems([helpButton, UIBarButtonItem(barButtonSystemItem: .FlexibleSpace, target: nil, action: nil), addButton], animated: false)

Resources