我正在进行一项应该适用于iOS 11和12的聊天。在iOS 12上,一切都按预期工作。但是,在iOS 11上,我遇到键盘出现时表视图内容大小增加(无单元格)的问题。额外高度的数量与键盘高度相匹配。
这是一个左侧是iOS 11,右侧是iOS 12的演示。在iOS 12上一切正常。当键盘出现时,请注意iOS 11上表格视图的底部。
-
=查看控制器
+
=查看
- UINavigationViewController
- UIViewController // Controlling contentInsets, contentOffset of the tableView
+ UIView
- UITableViewController
+ UITableView
- UIViewController // Controlling the text input bar at the bottom
+ ... // Other views
+ UITextView
表视图的锚点等于其superview的锚点。所以全屏,忽略安全区域。因此,当键盘出现时,框架不会改变,但底部内容会插入。
我设置了tableView.contentInsetAdjustmentBehavior = .never
这是我在键盘出现时计算表视图的插入和偏移的方法。这很复杂,因为有几种情况应该有不同的行为。当键盘消失时,以及文本输入的高度发生变化时,会出现类似的复杂计算。我总是想根据视图框架的变化向上或向下滚动表格视图。
@objc func handleKeyboardWillShowNotification(_ notification: NSNotification) {
let frameEnd: CGRect = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as AnyObject).cgRectValue ?? .zero
let keyboardHeight = frameEnd.height
let contentHeight = tableView.contentSize.height
let visibleTableViewHeight = tableView.frame.height - (tableView.contentInset.top + tableView.contentInset.bottom)
let distanceToScroll = (keyboardHeight - view.safeAreaInsets.bottom)
var y: CGFloat = 0
if contentHeight > visibleTableViewHeight {
y = tableView.contentOffset.y + distanceToScroll
} else {
let diff = visibleTableViewHeight - contentHeight
let positionAtKeyboard = distanceToScroll - tableView.contentInset.top - diff
y = positionAtKeyboard < tableView.contentInset.top ? -tableView.contentInset.top : positionAtKeyboard
}
let contentOffset = CGPoint(x: 0, y: y)
tableView.contentInset.bottom = keyboardHeight + inputBar.frame.height
tableView.scrollIndicatorInsets = tableView.contentInset
tableView.setContentOffset(contentOffset, animated: false)
}
我也尝试过不同的屏幕尺寸,它总是增加一个与键盘高度完全匹配的contentSize
。
首先,您不必进行不必要的计算只需计算键盘高度,然后将键盘向上移动即可。
Swift版本:
@objc func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
self.tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height + 10, right: 0)
UIView.animate(withDuration: 0.25) {
self.tableView.layoutIfNeeded()
self.view.layoutIfNeeded()
}
}
}
@objc func keyboardWillHide(notification: NSNotification) {
self.tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
UIView.animate(withDuration: 0.5) {
self.tableView.layoutIfNeeded()
self.view.layoutIfNeeded()
}
}
Objective-C版本:
- (void)keyboardWillShow:(NSNotification *)notification
{
NSDictionary *keyInfo = [notification userInfo];
CGRect keyboardFrame = [[keyInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
self.tableView.contentInset = UIEdgeInsetsMake(0, 0, keyboardFrame.size.height + 10, 0);
[UIView animateWithDuration:0.2 animations:^{
[self.tableView layoutIfNeeded];
[self.view layoutIfNeeded];
} completion:nil];
}
- (void) keyboardWillHide: (NSNotification *) notification
{
self.tableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);
[UIView animateWithDuration:0.2 animations:^{
[self.view layoutIfNeeded];
} completion:nil];
}
如果您发现任何困难,请告诉我。这对我很有用
您可以使用以下代码进行键盘隐藏和显示。
//显示键盘
@objc func keyboardWillAppear(_ notification: NSNotification) {
if let newFrame = (notification.userInfo?[ UIResponder.keyboardFrameEndUserInfoKey ] as? NSValue)?.cgRectValue {
if self.tableView.contentInset.bottom == 0 {
let insets: UIEdgeInsets = UIEdgeInsets( top: 0, left: 0, bottom: newFrame.height, right: 0 )
self.tableView.contentInset = insets
self.tableView.scrollIndicatorInsets = insets
UIView.animate(withDuration: 0.1) {
self.view.layoutIfNeeded()
}
}
}
}
//隐藏键盘
@objc func keyboardWillDisappear(_ notification: NSNotification) {
if self.tableView.contentInset.bottom != 0 {
self.tableView.contentInset = UIEdgeInsets( top: 0, left: 0, bottom: 0, right: 0 )
self.tableView.scrollIndicatorInsets = UIEdgeInsets( top: 0, left: 0, bottom: 0, right: 0 )
UIView.animate(withDuration: 0.1) {
self.view.layoutIfNeeded()
}
}
}
这对我有用。
这不是专门回答原始问题,但可能是那些没有半透明键盘和输入视图的人的解决方案。
我可以通过更改约束而不设置底部插入来解决此问题。最初,表视图的底部约束设置在超级视图的底部(基本上是屏幕的底部)。所以当键盘出现时,我没有改变表格视图的框架,而是底部插入。这显然不能正常工作。
现在我将表视图的底部约束设置为输入视图(黑色条)的顶部,将底部插入设置为零。由于输入视图在键盘出现时向上移动,因此它会更改表格视图的框架,并且底部插入保持为零。我仍然设置内容偏移,因为我需要在不同情况下的特定行为,但就是这样。
这只适用于我的情况,因为我既没有半透明的输入条也没有键盘,也不需要在它后面显示模糊的内容。