輸入框跟隨鍵盤彈出/隱藏移動

馬萬旻發表於2018-08-10

今天要做一個檢視跟隨鍵盤移動的功能,類似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並不只是在獲取焦點的時候呼叫,尤其是某些三方的鍵盤,可能會傳送多次通知,所以在處理輸入框位置的時候需要注意(我使用的使全域性記錄)。

相關文章