上一篇中我们把输入框和按钮归为了一组,按回车可以跳到下一项。接下来我们要获取键盘高度并对UIView进行调整。
1.先补充一些成员变量
//.m
@interface ViewController ()<UITextFieldDelegate> {
BOOL _isKeyboardShowing;
UITextField *_activeTextField;
BOOL _addedObserver;
NSArray *_inputFocuses;
BOOL _pressedReturn;
//-----------新代码-----------
float _keyboardHeight;
BOOL _invokeDelegateNow;
//---------------------------
}
2.接下来先从最简单的方法实现起来。隐藏键盘的时候恢复视图原有位置。
//.m
//-----------新代码-----------
- (void)hideKeyBoard {
NSTimeInterval animationDuration = 0.30f;
[UIView beginAnimations:@"ResizeForKeyboard" context:nil];
[UIView setAnimationDuration:animationDuration];
//将视图的Y坐标向上移动offset个单位,以使下面腾出地方用于软键盘的显示
self.view.bounds =CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height);
[UIView commitAnimations];
}
//---------------------------
3.实现KeyboardWillHide:消息。如果点击回车切换到下一个输入框,键盘会先消失,也会触发这个消息。所以我们只需要在点击输入框之外的时候隐藏键盘。否则视图会先回到原位再根据下一个文本框位置调整自己的位置,视觉上不连贯。
//.m
- (void)KeyboardWillHide:(NSNotification *)notification {
//-----------新代码-----------
_isKeyboardShowing = NO;
if (!_pressedReturn) {
[self hideKeyBoard];
}
else {
_pressedReturn = NO;
}
//---------------------------
}
- KeyboardWillShow:消息中获得键盘高度以后手动调用一次键盘代理方法textFieldDidBeginEditing:
//.m
- (void)KeyboardWillShow:(NSNotification *)notification {
_isKeyboardShowing = YES;
//-----------新代码-----------
NSDictionary *info = [notification userInfo];
//获取高度
NSValue *value = [info objectForKey:@"UIKeyboardBoundsUserInfoKey"];
if (!value) {
@throw [NSException exceptionWithName:@"error when getting Keyboard Rect" reason:@"maybe not supported in sdk" userInfo:nil];
}
CGSize keyboardSize = [value CGRectValue].size;
_keyboardHeight = keyboardSize.height;
_invokeDelegateNow = YES;
[self textFieldDidBeginEditing:_activeTextField];
//---------------------------
}
5.回到键盘代理方法之前先实现一个根据输入框位置调整UIView的方法。
//.m
//-----------新代码-----------
- (void)autoAdjustTextFieldHeight:(UITextField *)textField
{
CGRect frame = textField.frame;
CGPoint point = frame.origin;
CGRect viewBounds = self.view.bounds;
int offset = point.y + frame.size.height - (viewBounds.size.height - _keyboardHeight);
NSTimeInterval animationDuration = 0.30f;
[UIView beginAnimations:@"ResizeForKeyboard" context:nil];
[UIView setAnimationDuration:animationDuration];
//将视图的Y坐标向上移动offset个单位,以使下面腾出地方用于软键盘的显示
self.view.bounds = CGRectMake(0, offset > 0 ? ABS(offset) : 0, viewBounds.size.width, viewBounds.size.height);
[UIView commitAnimations];
}
//---------------------------
6.回到textFieldDidBeginEditing:,根据_invokeDelegateNow来决定是否调整视图高度。
//.m
- (void)textFieldDidBeginEditing:(UITextField *)textField {
_pressedReturn = NO;//按下return和直接点击text field都会触发这个方法,所以用一个标示的变量来区分,后面会发挥作用的。
_activeTextField = textField;
//-----------新代码-----------
//重要:这里的_invokeDelegateNow标记的作用是这样的,用户点击文本框会先触发这个代理方法,此时没有从KeyboardWillShow:的实现中获取键盘高度。_invokeDelegateNow会在KeyboardWillShow:中被标记为YES然后手动再次调用这个代理方法(不是由系统调用)。此时再执行调整视图高度的操作,才能根据键盘高度来调整。
if (_invokeDelegateNow) {
[self autoAdjustTextFieldHeight:textField];
}
//---------------------------
}
7.最后更新一下回车的方法。当回车以后的操作为点击按钮时,隐藏键盘。当回车的操作为跳到下一个输入框时,调整视图位置。
//.m
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
int index = [_inputFocuses indexOfObject:textField];
if (index == [_inputFocuses count] - 1) {//如果是最后一个text field时按return 就点击按钮
[self click:_button];
[self hideKeyBoard];
}
else {//如果没有到最后一个text field就将焦点转向下一个text field
UITextField *nextTextField = [_inputFocuses objectAtIndex:(index + 1)];
[nextTextField becomeFirstResponder];
[self autoAdjustTextFieldHeight:nextTextField];
}
UITextField *currentTextField = [_inputFocuses objectAtIndex:index];
[currentTextField resignFirstResponder];
return NO;
}
这就是我的解决方案,希望能够帮助到大家。如果代码用下来有什么问题,请留言。
工程已上传GitHub:https://github.com/manuqiao/TextFieldAutoAdjustment