Reputation: 3516
I have a view I'm trying to move when the keyboard appears/disappears. Here's the basic code.
func registerForKeyboardNotifications() {
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWasShown(_:)), name: .UIKeyboardDidShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillBeHidden(_:)), name: .UIKeyboardDidHide, object: nil)
}
@objc func keyboardWasShown(_ notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
if self.view.frame.origin.y == 0 {
print("\n\n\n\(keyboardSize.height)\n\n")
self.view.frame.origin.y -= keyboardSize.height
}
}
}
@objc func keyboardWillBeHidden(_ notification: NSNotification) {
self.view.frame.origin.y = 0
}
The first time it get's called, it prints 258.0, and the view moves up. Subsequent calls print 216.0. The keyboard moves up the same amount each time. The first time it moves the view the correct amount (the bottom the view is just above the keyboard), subsequent times the bottom part (42px) is behind the keyboard.
Any idea what might cause this?
Upvotes: 3
Views: 1404
Reputation: 2908
Instead of the UIKeyboardFrameBeginUserInfoKey
, use UIKeyboardFrameEndUserInfoKey
.
Moreover I would suggest you to use just one notification to handle all the changes to the frame as follows:
//Add keyboard did Layout change notification
NotificationCenter.default.addObserver(self,selector: #selector(self.keyboardNotification(notification:)),name:NSNotification.Name.UIKeyboardWillChangeFrame,object: nil)
And then implement it like this
@objc func keyboardNotification(notification: NSNotification) {
if let userInfo = notification.userInfo {
let endFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue
let endFrameY = endFrame?.origin.y ?? 0
let duration:TimeInterval = (userInfo[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0
let animationCurveRawNSN = userInfo[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber
let animationCurveRaw = animationCurveRawNSN?.uintValue ?? UIViewAnimationOptions.curveEaseInOut.rawValue
let animationCurve:UIViewAnimationOptions = UIViewAnimationOptions(rawValue: animationCurveRaw)
if endFrameY >= UIScreen.main.bounds.size.height {
//Change This
//self.signInButtonBottomConstraint?.constant = 0.0
} else {
//Modify This
//self.signInButtonBottomConstraint?.constant -= (endFrame?.size.height ?? 0.0)
}
UIView.animate(withDuration: duration,
delay: TimeInterval(0),
options: animationCurve,
animations: { self.view.layoutIfNeeded() },
completion: nil)
}
Upvotes: 6