如何获取当前输入控件?
如何获取键盘的高度和弹出键盘的动画时间?
如何计算需要 view 需要往上移动的偏移量?
多个输入控件时,如何保证 view 不乱跑?
第一步注册通知
注册键盘将要出现通知
注册键盘将要消失通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardHide:) name:UIKeyboardWillHideNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardShow:) name:UIKeyboardWillShowNotification object:nil];
获取当前输入控件
如果一个页面里有很多 UITextField 或 UITextView, 在键盘通知对应的方法中需要获取到具体是点击哪个输入控件弹出的键盘。都用全部变量的话,代码太冗余。而且,如果大堆的代码,看着也恶心。
思路:
点击输入控件,弹出键盘,
获取 window 第一响应者,第一响应者就是输入框
UITextField *tf = [self.view.window performSelector:@selector(firstResponder)];
如何获取键盘的高度和弹出键盘的动画时间?
- (void)keyboardShow:(NSNotification *)notifi
{
NSDictionary *userInfo = notifi.userInfo;
// 弹出事件
double duration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
// 键盘 frame
CGRect keyBoardframe = [notifi.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
}
如何计算需要 view 需要往上移动的偏移量?
先介绍三个变量:
- 键盘高度
- 输入控件底部间距 (输入控件底部相对于屏幕最下方的距离)
- 空白高度 (控制 输入控件底部和键盘顶部的间距)
CGFloat margin = keyBoardframe.size.height + spaceH - tf.bottomToSuper;
多个输入控件时,如何保证 view 不乱跑?
控制 view 上移动的时候,不要使用 += -= 这个操作符,多个输入框的时候,会跳
核心代码
- (void)keyboardShow:(NSNotification *)notifi
{
NSDictionary *userInfo = notifi.userInfo;
double duration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
CGRect keyBoardframe = [notifi.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGFloat spaceH = 40;
// 强迫症,不能忍警告
#pragma clang diagnostic push
#pragma clang diagnostic ignored"-Wundeclared-selector"
UITextField *tf = [self.view.window performSelector:@selector(firstResponder)];
#pragma clang diagnostic pop
CGFloat margin = keyBoardframe.size.height + spaceH - tf.bottomToSuper;
if (margin > 0) {
[UIView animateWithDuration:duration animations:^{
self.view.top = -margin;
}];
}
}
- (void)keyboardHide:(NSNotification *)notifi
{
NSDictionary *userInfo = notifi.userInfo;
double duration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
CGRect keyBoardframe = [notifi.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
#pragma clang diagnostic push
#pragma clang diagnostic ignored"-Wundeclared-selector"
UITextField *tf = [self.view.window performSelector:@selector(firstResponder)];
#pragma clang diagnostic pop
CGFloat margin = keyBoardframe.size.height + 40 - tf.bottomToSuper;
if (margin > 0) {
[UIView animateWithDuration:duration animations:^{
self.view.top = 0;
}];
}
}
补充
别忘了移除通知
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}