制作一个UITableView"粘在底部"

时间:2017-07-06 13:44:14

标签: ios swift uitableview

假设您有一个显示消息的表格视图,

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并且我不知道?

这里的问题再一次是

如何修改UITableView以便它移动自己的滚动位置,因为视图大小会发生变化......

(以便保持"底点相同")

请注意,只需滚动表格"手动"因为它来自外面。

3 个答案:

答案 0 :(得分:3)

章节标题贴在顶部,所以可能是这样的:
1.将最新消息设为节标题视图而不是表格单元格 2.垂直镜像表格视图:
tableView.transform = CGAffineTransformMakeScale(1, -1);
3.垂直镜像节标题和表格单元格 4.颠倒消息的顺序

那是你在找什么?

答案 1 :(得分:1)

这是一个方法的最新答案,但是我只比公认的非常巧妙的解决方案更优雅地解决了这个问题。

您需要具有以下AutoLayout约束(我将省略水平约束):

  • UITableView.top =安全区域.top
  • UITableView.bottom = MessageContainerView.top
  • MessageContainerView.bottom =安全区域.bottom

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);