我目前在键盘上有一个UITextField。点击它时,它应该粘在键盘顶部并平稳向上移动。我不知道键盘的确切持续时间和动画类型,所以它真的很颠簸。这就是我所拥有的:
[theTextView resignFirstResponder];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDelegate:self];
[UIView setAnimationDuration:0.25];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
// Frame changes go here (move down 216px)
[UIView commitAnimations];
[theTextView becomeFirstResponder];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDelegate:self];
[UIView setAnimationDuration:0.25];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
// Frame changes go here (move up 216px)
[UIView commitAnimations];
如果有人之前做过这样的事情,我想知道你用来使动画变得平滑的设置,并让它看起来像是“卡在”键盘的顶部。
答案 0 :(得分:45)
UIKit在显示键盘时发布UIKeyboardWillShowNotification
,在隐藏键盘时发布UIKeyboardWillHideNotification
。这些通知包含正确设置UITextField
动画所需的一切。
假设您的UITextField
位于名为myTextField
的属性中。
首先,您需要在某处注册通知。您注册的位置取决于移动myTextField
的对象。在我的项目中,该字段的superview负责,因为我从一个笔尖加载我的UI,我在superview的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];
}
如果您使用UIViewController
移动字段,则可能希望在viewWillAppear:animated:
中执行此操作。
您应该在dealloc
或viewWillDisappear:animated:
:
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
当然,棘手的一点是keyboardWillHideOrShow:
方法。首先,我从通知中提取动画参数:
- (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];
keyboardFrame
位于全局坐标系中。我需要将帧转换为与myTextField.frame
相同的坐标系,而myTextField.frame
位于myTextField.superview
的坐标系中:
CGRect keyboardFrameForTextField = [self.myTextField.superview convertRect:keyboardFrame fromView:nil];
接下来,我计算我希望myTextField
移动到的帧。新帧的下边缘应该等于键盘框架的上边缘:
CGRect newTextFieldFrame = self.myTextField.frame;
newTextFieldFrame.origin.y = keyboardFrameForTextField.origin.y - newTextFieldFrame.size.height;
最后,我使用键盘正在使用的相同动画参数将myTextField
设置为新帧:
[UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionBeginFromCurrentState | curve animations:^{
self.myTextField.frame = newTextFieldFrame;
} completion:nil];
}
这里全部放在一起:
- (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];
}
答案 1 :(得分:5)
将文本字段(或包含文本字段的视图)设置为您正在编辑的字段的inputAccessoryView
。然后它会自动连接到键盘顶部并进行适当的动画制作。
答案 2 :(得分:0)
为了使UITextField停靠到键盘(带动画),您需要使用setContentOffset:animation:
方法进行偏移计算并在滚动视图上应用偏移更改(假设UITextField放在UIScrollView中)。
答案 3 :(得分:0)
在键盘通知中使用以下代码:
@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)
}