我正在进行的聊天应在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
表视图的锚点等于其父视图的锚点。如此全屏显示,忽略了安全区域。因此,当键盘出现时,框架不会改变,但底部内容会插入。
我设置了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
添加一个与键盘高度完全匹配的数量。
答案 0 :(得分:0)
首先,您不必进行不必要的计算 只需计算键盘高度,然后将键盘向上移动即可。
快速版本:
@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];
}
如果您遇到任何困难,请告诉我。 这对我很有效
答案 1 :(得分:0)
您可以使用以下代码进行键盘的隐藏和显示。
//显示键盘。
@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()
}
}
}
这对我有用。
答案 2 :(得分:0)
这不是专门回答原始问题的方法,但是对于那些没有半透明键盘和输入视图的人来说,这可能是一个解决方案。
我可以通过更改约束而不设置底部插图来解决此问题。最初,表视图的底部约束设置为超级视图的底部(基本上是屏幕的底部)。因此,当键盘出现时,我没有更改表格视图的框架,而是底部的插图。这显然不能正常工作。
现在,我已将表视图的底部约束设置为输入视图的顶部(黑条),并将底部插图设置为零。由于输入视图在出现键盘时会向上移动,因此它将更改表格视图的框架,并且底部插图保持为零。我仍然设置内容偏移量,因为在不同情况下我需要特定的行为,仅此而已。
这仅在我的情况下有效,因为我既没有半透明的输入栏,也没有键盘,也不需要在其后面显示模糊的内容。