假设您有一个显示消息的表格视图,
T[ message d
T[ message c
T[ message b
T[ most recent message down bottom
假设有100条消息,示例中底部4可见。
所以表视图高度是700说。您有一个典型的文字条目......
T[ message d
T[ message c
T[ message b
T[ most recent message down bottom
[enter snapped chat message!] [send]
当键盘出现时,可见表格视图的新高度为400。
当然,那将"切断底部"消息 - 最近的两个将不再可见。
T[ message d
T[ message c
[enter snapped chat message!] [send]
[ iOS keyboard ]
[ iOS keyboard ]
(因此,消息A和B现在是"在"键盘下面。)
当然,您所做的只是在键盘出现后滚动表格,例如。没有问题以临时方式进行。
然而,如果可以通过以下方式继承UITableView,那将是非常自然的,因为随着可见区域的大小发生变化,表格视图知道保持"底点"相同
因此,当桌子的底部上下移动时(由于键盘出现 - 或者其他原因),桌子实际上会根据" base"的移动而滚动。该表。
(除了其他任何东西,这将解决"匹配动画时间"滋扰。)
这可以优雅地实现,如果是这样的话 - 这些日子看起来如此自然,或许它作为旗帜内置于UITableView并且我不知道?
这里的问题再一次是
(以便保持"底点相同")
请注意,只需滚动表格"手动"因为它来自外面。
答案 0 :(得分:3)
章节标题贴在顶部,所以可能是这样的:
1.将最新消息设为节标题视图而不是表格单元格
2.垂直镜像表格视图:
tableView.transform = CGAffineTransformMakeScale(1, -1);
3.垂直镜像节标题和表格单元格
4.颠倒消息的顺序
那是你在找什么?
答案 1 :(得分:1)
这是一个方法的最新答案,但是我只比公认的非常巧妙的解决方案更优雅地解决了这个问题。
您需要具有以下AutoLayout约束(我将省略水平约束):
MessageContainerView
是我保留消息文本视图和按钮的位置。现在,在您的ViewController
中,为IBOutlet
的底部约束添加一个MessageContainerView
:
@IBOutlet weak var messageContainerBottomConstraint: NSLayoutConstraint!
下一步是将底部约束的常量设置为等于键盘高度+底部安全区域的动画,并在显示键盘时将表格滚动到底部(同时为通知添加观察者):>
@objc func showKeyboard(_ notification: NSNotification) {
guard let userInfo = notification.userInfo,
let targetFrame = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue,
let animationTime = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double
else {
return
}
let safeAreaBottom = view.safeAreaInsets.bottom
messageContainerBottomConstraint.constant = -targetFrame.cgRectValue.height + safeAreaBottom
UIView.animate(withDuration: animationTime) {
self.view.layoutIfNeeded()
self.tableView.scrollToBottom()
}
}
请注意,我们将UIResponder.keyboardAnimationDurationUserInfoKey
用作动画时间,因此一切都会变得流畅。
最后,tableView.scrollToBottom()
是UITableView
的扩展:
import UIKit
extension UITableView {
func scrollToBottom() {
let numberOfSections = self.numberOfSections
let numberOfRowsInSection = self.numberOfRows(inSection: numberOfSections - 1)
let indexPathForLastRow = IndexPath(row: numberOfRowsInSection - 1, section: numberOfSections - 1)
self.scrollToRow(at: indexPathForLastRow, at: .bottom, animated: false)
}
}
让我知道您是否可以尝试一下,以及是否错过了任何事情。
(我确实注意到您要求修改原生UITableView
行为的方法,而不是“手动”滚动,但是我认为这是解决问题的有效方法)
答案 2 :(得分:0)
据我所知,你有几个选择:
如果您想要显示行的indexPath:
tableView.ScrollToRow(indexPath, UITableViewScrollPosition.Top, true);
这将滚动到indexPath给出的单元格。在这种情况下,您选择在屏幕的.Top
上显示该选项。
如果您没有indexPath,可以使用:
tableView.ScrollRectToVisible(new RectangleF(0, Ydisplacement, tableView.Width, tableView.Height), true);