快速消息应用程序,uitableview 无法正确响应键盘?

Posted

技术标签:

【中文标题】快速消息应用程序,uitableview 无法正确响应键盘?【英文标题】:swift messaging app, uitableview not responding correctly to keyboard? 【发布时间】:2018-03-22 15:07:22 【问题描述】:

一个类似的问题是this,除了我没有估计的行高,我将实际高度存储到字典中,然后使用它们,或者使用UITableViewAutomaticDimension

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) 
    cellHeightDict[indexPath.row] = cell.frame.size.height


func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat 
    if let height = cellHeightDict[indexPath.row] 
        return height
     else 
        return UITableViewAutomaticDimension
    


func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat 
    if let height = cellHeightDict[indexPath.row] 
        return height
     else 
        return UITableViewAutomaticDimension
    

所以我现在正在用 Swift 4 制作一个消息传递应用程序。当用户显示键盘时,我希望消息随着键盘向上移动。所以为了做到这一点,我有一个变量keyboardHeight,它正确得到了键盘的高度:

let keyboardHeight: CGFloat = ((userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.height)!

我将表格视图的高度更改为keyboardHeight

self.messageTableViewHeight.constant -= keyboardHeight

因此用户可以看到所有的消息。为了通过键盘动画上移消息,我更改了 table view 的 contentOffset:

self.messageTableView.contentOffset.y += keyboardHeight

所有这些都在UIView.animationWithDuration 中,之后我调用self.view.layoutIfNeeded(),因此转换和一切正常。 但是,当我发送消息时没有滚动到底部,messageTableView 的内容会向下跳??? 而且它似乎向下移动了keyboardHeight,至少当我看着它。我正在使用messageTableView.reloadData()。这是一些图片。

Before message sent

它在“Hi”和“Testing”消息之间跳跃。

After message sent

【问题讨论】:

对于文本输入位于最底部的聊天应用程序,通常您只需将视图控制器的整个视图向上移动键盘高度即可 我试过这样做,但是我如何让用户看到所有的消息?如果我将整个表格视图向上移动,那么它会在标题下方滑动。 我想把它向上移动,然后调整 contentInset,但是滚动条会滚动到视图之外,插入行也是一个问题。 【参考方案1】:

只要你重新加载 tableview messageTableView.reloadData() 的数据。每行都会重新加载,但它无法以某种方式计算实际的内容大小。您可以尝试重新加载主队列中的数据。

DispatchQueue.main.async 
    messageTableView.reloadData()

如果仍然无法正常工作,您可以在上面的代码中再添加一件事。假设您的班级中有一组消息。 var messages 那么你就可以使用这段代码在tableview中正确显示数据了。

DispatchQueue.main.async 
    messageTableView.reloadData()
    if messages.count > 0 
        let indexPath = IndexPath(row: messages.count - 1, section: 0)
        self.messageTableView.scrollToItem(at: indexPath, at: .bottom, animated: true)
    

希望这会有所帮助。编码愉快。

【讨论】:

基本上每次 ui 更新都应该在主线程上完成,在重新加载数据后,我们只是将 tableview 滚动到最后一个单元格的底部位置。 所以当我更新约束或使用 UIView.animate 时,我应该使用 DispatchQueue.main.async 吗?抱歉,我还是个初学者。 在动画的情况下,一旦你通过了块,它就会立即被调用,所以你不需要把它们放在任何队列中。操作系统通常会自行处理所有动画。但这里有个问题,假设您正在后台线程中执行某些操作,并且您需要使用动画更新 UI,那么您必须返回主队列来执行动画。这完全取决于您的代码是如何执行的。

以上是关于快速消息应用程序,uitableview 无法正确响应键盘?的主要内容,如果未能解决你的问题,请参考以下文章

带有 UITableView 的 UITabBar - 我可以正确看到表格,但无法选择一行

UITableView“有时”无法正确绘制单元格

如果无法从 Firebase 实时数据库中检索数据,则尝试在 UITableView 上显示消息

无法更改 uitableView 中的按钮图像

UITableView 内的 UIScrollView 无法正确显示/隐藏(Xcode iPhone)

UITableView 在 iOS 7.1 上无法正确重新加载