输入框跟随键盘弹出/隐藏移动

932 阅读1分钟

今天要做一个视图跟随键盘移动的功能,类似qq微信那种聊天输入框。之前已经做过无数次了,今天记录下实现方法和两个小坑。

以下是注册通知和通知实现方法,键盘通知百度一堆,不做赘述了。(记得移除通知)

- (void)registerNotice {
    [MMNotificationCenter addObserver:self selector:@selector(showKeyboard:) name:UIKeyboardWillShowNotification object:nil];
    [MMNotificationCenter addObserver:self selector:@selector(hideKeyboard:) name:UIKeyboardWillHideNotification object:nil];
}

- (void)showKeyboard:(NSNotification *)notice {
    NSLog(@"%@", notice.userInfo);
    // 获取键盘的位置和大小
    CGRect keyboardBounds;
    [[notice.userInfo valueForKey:UIKeyboardFrameEndUserInfoKey] getValue: &keyboardBounds];
    NSNumber *duration = [notice.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey];
    NSNumber *curve = [notice.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey];
    
    // Need to translate the bounds to account for rotation.
    keyboardBounds = [self.view convertRect:keyboardBounds toView:nil];
    
    // 获取输入框的位置和大小
    CGRect containerFrame = self.sendView.frame;
    // 计算出输入框的高度
    containerFrame.origin.y = _originPointY - keyboardBounds.size.height;
    
    // 动画改变位置
    [UIView animateWithDuration:[duration doubleValue] animations:^{
        [UIView setAnimationBeginsFromCurrentState:YES];
        [UIView setAnimationDuration:[duration doubleValue]];
        [UIView setAnimationCurve:[curve intValue]];
        // 更改输入框的位置
        self.sendView.frame = containerFrame;
    }];
}

- (void)hideKeyboard:(NSNotification *)notice {
    CGRect keyboardBounds;
    [[notice.userInfo valueForKey:UIKeyboardFrameEndUserInfoKey] getValue: &keyboardBounds];
    NSNumber *duration = [notice.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey];
    NSNumber *curve = [notice.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey];
    
    // Need to translate the bounds to account for rotation.
    keyboardBounds = [self.view convertRect:keyboardBounds toView:nil];
    
    // 获取输入框的位置和大小
    CGRect containerFrame = self.sendView.frame;
    containerFrame.origin.y = _originPointY;
    
    // 动画改变位置
    [UIView animateWithDuration:[duration doubleValue] animations:^{
        [UIView setAnimationBeginsFromCurrentState:YES];
        [UIView setAnimationDuration:[duration doubleValue]];
        [UIView setAnimationCurve:[curve intValue]];
        // 更改输入框的位置
        self.sendView.frame = containerFrame;
    }];
}

主要记录以下两个坑:

  1. 我的布局最初是使用masonry的,也就是使用了autoLayout,但是在动画效果的时候改变了frame,这样会造成一些奇奇怪怪的问题,所以之后统一使用了frame布局。(具体原因与使用autoLayout布局点这里)
  2. UIKeyboardWillShowNotification并不只是在获取焦点的时候调用,尤其是某些三方的键盘,可能会发送多次通知,所以在处理输入框位置的时候需要注意(我使用的使全局记录)。