当键盘出现在 iOS11 上时,UITableView 将键盘的高度添加到 contentSize

Luk*_*ger 5 uitableview uiscrollview ios swift ios11

我正在处理一个应该在 iOS 11 和 12 上工作的聊天。在 iOS 12 上一切都按预期工作。但是,在 iOS 11 上,我遇到了键盘出现后表格视图内容大小增加(无单元格)的问题。额外高度的数量与键盘高度相匹配。

演示

这是一个演示,左边是 iOS 11,右边是 iOS 12。在 iOS 12 上一切正常。当键盘出现时,请注意 iOS 11 上表格视图的底部。

表视图内容大小 iOS 11 表视图内容大小 iOS 12

视图/视图控制器层次结构设置

-= 视图控制器
+= 视图

- UINavigationViewController
    - UIViewController // Controlling contentInsets, contentOffset of the tableView
        + UIView
        - UITableViewController
            + UITableView
        - UIViewController // Controlling the text input bar at the bottom
            + ... // Other views
            + UITextView
Run Code Online (Sandbox Code Playgroud)

布局约束

表视图的锚点等于其超视图的锚点。所以全屏,忽略安全区域。所以当键盘出现时,框架不会改变,但底部的内容会插入。

更多细节

我已经设置了 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)
}
Run Code Online (Sandbox Code Playgroud)

我也在不同的屏幕尺寸上尝试过这个,它总是增加一个contentSize与键盘高度完全匹配的数量。

Luk*_*ger 0

解决方法

这并不是专门回答原来的问题,但对于那些没有半透明键盘和输入视图的人来说可能是一个解决方案。

我可以通过更改约束而不设置底部插图来解决这个问题。最初,表视图的底部约束设置为超级视图的底部(基本上是屏幕的底部)。因此,当键盘出现时,我没有更改表格视图的框架,而是更改了底部插图。这显然没有正常工作。

现在,我已将表视图的底部约束设置为输入视图的顶部(黑色条),并将底部插入设置为零。由于输入视图在键盘出现时向上移动,因此它改变了表格视图的框架并且底部插入保持为零。我仍然设置内容偏移量,因为我需要在不同情况下的特定行为,但仅此而已。

这仅适用于我的情况,因为我既没有半透明的输入栏也没有键盘,也不需要在其后面显示模糊的内容。