I currently have a UITextField on top of a keyboard. When you tap it, it should stick on top of the keyboard and move up smoothly. I don\'t know the exact duration and anima
Set your text field (or a view holding the text field) as the inputAccessoryView
of the field that you are editing. It will then automatically be attached to the top of the keyboard and animate appropriately.
in order to make the UITextField to dock to keyboard (with animation), you need to do offset calculations and apply offset changes on the scroll view (assuming UITextField is placed in UIScrollView) using setContentOffset:animation:
method.
Use this code in your keyboard notification:
@objc func keyboardWillShowNotification(notification: Notification) {
let keyboardHeight = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.size.height ?? 216
let duration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? Double ?? 0.25
let curve = (notification.userInfo?[UIKeyboardAnimationCurveUserInfoKey] as? UInt ?? 7) << 16
tableViewBottomConstraint.constant = keyboardHeight - submitButtonContainer.frame.size.height
UIView.animate(withDuration: duration, delay: 0, options: [UIViewAnimationOptions(rawValue: curve)], animations: {
// Animation
}, completion: nil)
}
UIKit posts UIKeyboardWillShowNotification
when it shows the keyboard, and UIKeyboardWillHideNotification
when it hides the keyboard. These notifications contain everything you need to properly animate your UITextField
.
Let's say your UITextField
is in a property called called myTextField
.
First, you need to register for the notifications somewhere. Where you register depends on what object is responsible for moving myTextField
. In my project, the field's superview is responsible, and since I load my UI from a nib, I do it in the superview's awakeFromNib
:
- (void)awakeFromNib
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHideOrShow:) name:UIKeyboardWillHideNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHideOrShow:) name:UIKeyboardWillShowNotification object:nil];
}
If you use a UIViewController
to move the field around, you'll probably want to do it in viewWillAppear:animated:
.
You should unregister in your dealloc
or viewWillDisappear:animated:
:
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
Of course the tricky bit is in the keyboardWillHideOrShow:
method. First I extract the animation parameters from the notification:
- (void)keyboardWillHideOrShow:(NSNotification *)note
{
NSDictionary *userInfo = note.userInfo;
NSTimeInterval duration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
UIViewAnimationCurve curve = [[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue];
CGRect keyboardFrame = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
The keyboardFrame
is in the global coordinate system. I need to convert the frame to the same coordinate system as myTextField.frame
, and myTextField.frame
is in the coordinate system of myTextField.superview
:
CGRect keyboardFrameForTextField = [self.myTextField.superview convertRect:keyboardFrame fromView:nil];
Next, I compute the frame that I want myTextField
to move to. The bottom edge of the new frame should be equal to the top edge of the keyboard's frame:
CGRect newTextFieldFrame = self.myTextField.frame;
newTextFieldFrame.origin.y = keyboardFrameForTextField.origin.y - newTextFieldFrame.size.height;
Finally, I animate myTextField
to its new frame, using the same animation parameters that the keyboard is using:
[UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionBeginFromCurrentState | curve animations:^{
self.myTextField.frame = newTextFieldFrame;
} completion:nil];
}
Here it is all put together:
- (void)keyboardWillHideOrShow:(NSNotification *)note
{
NSDictionary *userInfo = note.userInfo;
NSTimeInterval duration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
UIViewAnimationCurve curve = [[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue];
CGRect keyboardFrame = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGRect keyboardFrameForTextField = [self.myTextField.superview convertRect:keyboardFrame fromView:nil];
CGRect newTextFieldFrame = self.myTextField.frame;
newTextFieldFrame.origin.y = keyboardFrameForTextField.origin.y - newTextFieldFrame.size.height;
[UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionBeginFromCurrentState | curve animations:^{
self.myTextField.frame = newTextFieldFrame;
} completion:nil];
}