交互关闭键盘时 UITableView contentInset 不更新

UITableView contentInset not updating when keyboard interactively dismissed

更新

我发现在我的许多重构中,我继承自 UIViewController 而不是 UITableViewController,因此我缺少 UITableViewController 提供的一些自动行为。但是,当键盘被交互关闭时,我仍然需要手动处理滚动视图插图。查看我更新的答案。


我正在尝试模拟 iMessage 在用户将键盘拖动到屏幕底部时键盘是如何消失的。我用它解决了一个困扰我的小视觉问题。

当键盘被拖离屏幕时,滚动指示器不会正确调整大小 - 直到它被完全关闭。

我使用键盘通知来告诉我何时出现键盘以增加内容并滚动键盘的高度。当键盘被关闭时,我似乎不需要做任何事情,因为插图看起来是正确的。但是,当以交互方式关闭时,我无法在拖动事件期间更新插图。

为了说明这个问题,第一张图片显示由于 space 被键盘占用,内容已经滚出屏幕顶部;用户已滚动到 table:

中的最后一行

在这里,键盘被关闭,几乎完全不在屏幕上。但是请注意滚动指示器的大小完全错误。现在所有内容几乎都在屏幕上,因此指示器应该会拉伸,但是,当键盘向下移动时,滚动指示器会向上移动并且不会拉伸。这不是 iMessage 中发生的事情。

我认为我所做的非常标准,我正在创建一个 UIToolBar (iOS 8.3) 并在我的视图控制器中覆盖这些方法:

override var inputAccessoryView: UIView {
    return toolbar
}

override func canBecomeFirstResponder() -> Bool {
    return true
}

func willShowKeyboard(notification: NSNotification) {
    let keyboardFrame = notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue
    tableView.contentInset.bottom = keyboardFrame.CGRectValue().height
    tableView.scrollIndicatorInsets.bottom = keyboardFrame.CGRectValue().height
}

更新

切换到 UITableViewController 后,我发现 scrollViewDidScroll() 的实现(以及下面原始解决方案中的其他方法)实现了在键盘按下时动态调整插图大小的技巧交互解雇。

override func scrollViewDidScroll(scrollView: UIScrollView) {

    if !keyboardShowing {
        return
    }

    let toolbarFrame = toolbar.convertRect(toolbar.frame, toView: nil)

    tableView.scrollIndicatorInsets.bottom = view.bounds.height - toolbarFrame.minY
    tableView.contentInset.bottom = view.bounds.height - toolbarFrame.minY
}

我已经设法达到了同样的效果。我不确定这是否是 correct 方法,但效果很好。我很想知道可能还有哪些其他解决方案。

func didShowKeyboard(notification: NSNotification) {
    let keyboardFrame = notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue
    let keyboardHeight = keyboardFrame.CGRectValue().height

    tableView.contentInset.bottom = keyboardHeight
    tableView.scrollIndicatorInsets.bottom = keyboardHeight

    keyboardShowing = true
}

func didHideKeyboard(notification: NSNotification) {
    keyboardShowing = false
}

func scrollViewDidScroll(scrollView: UIScrollView) {

    if !keyboardShowing {
        return
    }

    let toolbarFrame = view.convertRect(toolbar.frame, fromView: toolbar)

    tableView.scrollIndicatorInsets.bottom = view.bounds.height - toolbarFrame.minY
    tableView.contentInset.bottom = view.bounds.height - toolbarFrame.minY
}