iPhone X键盘出现显示额外空间

我创建了一个聊天UI,我在其中为tableView添加了一个constraint到屏幕底部。 我正在通过添加键盘的高度来更改约束值,该键盘在除iPhone X之外的所有设备中都能正常工作。

键盘不可见时的UI:

在此处输入图像描述

哪个好。

问题是当键盘出现空白区域在textView和键盘之间可见时:

在此处输入图像描述

我是否必须为此尝试不同的方法,或者可以使用约束来解决它?

尝试在计算约束的值时减去安全区域底部插入的高度。

以下是处理UIKeyboardWillChangeFrame通知的示例实现。

 @objc private func keyboardWillChange(_ notification: Notification) { guard let userInfo = (notification as Notification).userInfo, let value = userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue else { return } let newHeight: CGFloat if #available(iOS 11.0, *) { newHeight = value.cgRectValue.height - view.safeAreaInsets.bottom } else { newHeight = value.cgRectValue.height } myConstraint.value = newHeight } 

ViewController制作约束出口。 我现在将它称为你的yourConstraint 。 然后添加代码以发现键盘何时显示以及何时被解除键盘。 你可以相应地改变约束的constant 。 这允许您继续使用约束。

viewWillAppear

 NotificationCenter.default.addObserver(self, selector: #selector(YourViewController.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil) // <=== Replace YourViewController with name of your view controller NotificationCenter.default.addObserver(self, selector: #selector(YourViewController.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil) // <=== Replace YourViewController with name of your view controller 

viewWillDisappear

 NotificationCenter.default.removeObserver(self) 

在你的UIViewController

 @objc private func keyboardWillShow(notification: Notification) { guard let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue else { yourConstraint.isActive = false // <=== view.layoutIfNeeded() return } let duration: TimeInterval = ((notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue) ?? 0.4 yourConstraint.constant = newValue // <=== UIView.animate(withDuration: duration) { self.view.layoutIfNeeded() } } @objc private func keyboardWillHide(notification: Notification) { let duration: TimeInterval = ((notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue) ?? 0.4 yourConstraint.constant = oldValue UIView.animate(withDuration: duration) { self.view.layoutIfNeeded() } } 

UIView.animate不是必需的(块的内部是),但它使转换看起来很好。

在iPhone X中,UIKeyboardFrame Begin UserInfoKey报告的键盘值在这两种情况下是不同的:

  • 键盘不可见,文本字段成为第一响应者
  • 键盘已经可见,不同的文本字段成为第一响应者。

要获得键盘键盘的最终高度(包括安全区域插入),请使用UIKeyboardFrame End UserInfoKey。

在iOS 11(特别是iPhone X)中,您可以考虑减去安全区域底部插入。

  NSValue *keyboardEndFrameValue = notification.userInfo[UIKeyboardFrameEndUserInfoKey]; if (keyboardEndFrameValue != nil) { CGRect keyboardSize = [keyboardEndFrameValue CGRectValue]; _keyboardHeight = keyboardSize.size.height; if (@available(iOS 11.0, *)) { CGFloat bottomSafeAreaInset = self.view.safeAreaInsets.bottom; _keyboardHeight -= bottomSafeAreaInset; } else { // Fallback on earlier versions } } 

Swift 4 iPhone X我不得不稍微调整一下Nathan的答案才能让它发挥作用。 100%这个。

注意:确保从视图控制器中将文本视图/视图的底部约束从故事板拖动到安全区域的底部,并确保在目标视图控制器项目导航器中拖动并创建了一个sockets。 我在我的例子中将它命名为bottomConstraint。 我的文本输入字段包含在视图(messageInputContainerView)中,以允许其他发送按钮对齐等。

约束演示

这是代码:

 @objc private func keyboardWillChange(_ notification: Notification) { guard let userInfo = (notification as Notification).userInfo, let value = userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue else { return } if ((userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue) != nil { let isKeyboardShowing = notification.name == NSNotification.Name.UIKeyboardWillShow var newHeight: CGFloat if isKeyboardShowing { if #available(iOS 11.0, *) { newHeight = value.cgRectValue.height - view.safeAreaInsets.bottom bottomConstraint.constant = newHeight } } else { newHeight = value.cgRectValue.height bottomConstraint?.constant = view.safeAreaInsets.bottom + messageInputContainerView.bounds.height } } }