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 } } }