我有一个ViewController
,其中有几个使用键盘输入的常规文本字段,还有一个UITextView
,其UIPickerView
实现了inputView
。当这些字段中的每个字段更改为firstResponder
时,显示/隐藏动画都可以正常工作……除非用户从一种类型的字段切换到另一种类型,否则就没有动画。旧的输入设备消失,并立即由新的输入设备替换。在这种情况下,我不知道如何启用动画。
下面的代码可以正常工作,除了此过渡。我考虑过延迟两个项目的出现,但是我不知道如何检测问题情况。
//MARK: - Keyboard repositioning
extension DetailViewController {
func registerForKeyboardNotifications() {
//Adding notifies on keyboard appearing
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWasShown(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillBeHidden(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil)
}
func deregisterFromKeyboardNotifications() {
//Removing notifies on keyboard appearing
NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
}
@objc func keyboardWasShown(notification: NSNotification) {
let horizontalCenter = self.view.frame.width / 2
var info = notification.userInfo!
let keyboardFrame: CGRect = (info[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
let keyboardHeight = keyboardFrame.size.height
let keyboardCenterTopInPresentingVC = CGPoint(x: horizontalCenter, y: keyboardHeight)
let keyboardCenterTopInThisVC = self.presentingViewController?.view.convert(keyboardCenterTopInPresentingVC, to: self.view) ?? keyboardCenterTopInPresentingVC
//the distance to push the Cancel/Add buttons up by
let adjustment = keyboardCenterTopInThisVC.y
//use standard keyboard animation timing
let duration = notification.userInfo![UIResponder.keyboardAnimationDurationUserInfoKey] as! Double
UIView.animate(withDuration: duration) { () -> Void in
self.stackViewBottomConstraint.constant = adjustment - self.stackViewBottomConstraintInitialValue!
self.view.layoutIfNeeded()
}
}
@objc func keyboardWillBeHidden(notification: NSNotification) {
//Once keyboard disappears, restore original positions
var info = notification.userInfo!
let duration = info[UIResponder.keyboardAnimationDurationUserInfoKey] as! Double
//use standard keyboard animation timing
UIView.animate(withDuration: duration) { () -> Void in
self.stackViewBottomConstraint.constant = self.stackViewBottomConstraintInitialValue!
self.view.layoutIfNeeded()
}
}
}
//MARK: - UIPickerView support
extension DetailViewController: UIPickerViewDelegate, UIPickerViewDataSource {
func createPickerView(for thisField: UITextField) {
let pickerView = UIPickerView()
thisField.inputView = pickerView
pickerView.delegate = self
let currentFieldValueIndex = sectionHeaderItems.firstIndex{ $0.title == thisField.text}
pickerView.selectRow(currentFieldValueIndex!, inComponent: 0, animated: true)
let doneButton = UIBarButtonItem.init(title: "Done", style: .done, target: self, action: #selector(self.pickerDone))
let toolBar = UIToolbar.init(frame: CGRect(x: 0, y: 0, width: view.bounds.size.width, height: 44))
toolBar.setItems([UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.flexibleSpace, target: nil, action: nil), doneButton],
animated: true)
thisField.inputAccessoryView = toolBar
}
@objc
func pickerDone() {
priorityGroupLabel.resignFirstResponder()
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return sectionHeaderItems.count
}
func pickerView( _ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return sectionHeaderItems[row].title
}
func pickerView( _ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
let newPriorityGroup = Int16(sectionHeaderItems[row].index)
priorityGroupLabel.text = sectionHeaderItems[row].title
if newPriorityGroup == originalPriorityGroup {
//reverted to no change from saved data
priorityGroupForDisplay = originalPriorityGroup!
priorityForDisplay = originalPriority!
numItemsForDisplay = Int(itemsInCurrentGroup)
} else {
//Priority Group has been changed
priorityGroupForDisplay = newPriorityGroup
numItemsForDisplay = Int(itemsInCurrentGroup + 1)
if positionSegCtlStack.isHidden == false && positionSegCtl.selectedSegmentIndex == 0 { //Top
priorityForDisplay = 1
} else {
priorityForDisplay = Int16(numItemsForDisplay)
}
}
}
}