如何避免键盘遮挡UITextField的解决方案(下)

上一篇中我们把输入框和按钮归为了一组,按回车可以跳到下一项。接下来我们要获取键盘高度并对UIView进行调整。

1.先补充一些成员变量
//.m

@interface ViewController () {
    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;
    }
    //---------------------------
}
  1. 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

你可能感兴趣的:(如何避免键盘遮挡UITextField的解决方案(下))