我有一个带自动调整大小的UITableView。每个单元格的内容围绕着时间的计算,因此单元格的大小可能每秒都在变化。我目前正在使用每1秒安排一次的计时器告诉表视图更新单元格大小:
Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(timeUpdateNotification), userInfo: nil, repeats: true)
@objc func timeUpdateNotification() {
// ... cells get notified to update contents here ...
tableView.beginUpdates()
tableView.endUpdates()
}
这工作得相当好,但是当用户点击滚动到列表顶部时会出现问题。动画有点笨拙,往往没有时间到顶部。有没有更好的方法来处理这个?
如果在滚动表时设置了标志,则可以在计时器功能中检测到该标志,并在设置时不进行更新。 UITableView
是UIScrollView
的后代,因此您可以使用一些滚动视图代表来执行此操作。如果您覆盖scrollViewShouldScrollToTop()
和scrollViewDidScrollToTop()
,您将知道滚动视图何时滚动到顶部以及何时完成。
override func scrollViewShouldScrollToTop(_ scrollView: UIScrollView) -> Bool {
NSLog("scrollViewShouldScrollToTop")
isScrolling = true
return true
}
override func scrollViewDidScrollToTop(_ scrollView: UIScrollView) {
NSLog("scrollViewDidScrollToTop")
isScrolling = false
}
您还可以对此进行扩展以检测用户何时拖动/滚动视图,以防止计时器功能在这些情况下也更新。
override func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
NSLog("scrollViewWillBeginDragging")
isScrolling = true
}
override func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
if (!decelerate) {
// Only catch if scrolling stopped
NSLog("scrollViewDidEndDragging")
isScrolling = false
}
}
override func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
NSLog("scrollViewDidEndDecelerating")
isScrolling = false
}
我已经在函数中添加了一些日志记录,以便您可以看到正在发生的事情。当然,你可以删除这些。
当点击滚动到顶部时,计时器无效,然后一旦到达顶部再次启动计时器。
编辑:这样,它不会更新可能在不更新表格视图的“顶部”的情况下移动内容更高的内容。
我遇到了类似的问题。我借助每个单元格的手动高度计算解决了这个问题。
var cellHeights: [Int: CGFloat] = [:]
在cellForRowAtIndexPath方法中,计算高度:
cellHeights[byRow] = cell.getCellHeight()
在细胞本身
func getCellHeight() -> CGFloat {
let userInfoHeight: CGFloat = userInfoHeightConstraint.constant
let actionHeight: CGFloat = actionViewHeightConstraint.constant
let descriptionBottom: CGFloat = descriptionBottomConstraint.constant
let descriptionWidth = self.frame.width - leftAvatarConstraint.constant - descriptionRightConstraint.constant
let descriptionHeight: CGFloat = descriptionLabel.textHeight(width: descriptionWidth)
let height = userInfoHeight + actionHeight + descriptionBottom + descriptionHeight
return height
}
extension UILabel {
func textHeight(width: CGFloat) -> CGFloat {
var textHeight: CGFloat = 0
if let text = self.text {
let customLabel = UILabel(frame: CGRect(x: 0, y: 0, width: width, height: .greatestFiniteMagnitude))
customLabel.numberOfLines = self.numberOfLines
customLabel.text = text
customLabel.font = self.font
customLabel.sizeToFit()
textHeight = customLabel.frame.height
}
return textHeight
}}
我正在使用UITableViewAutomaticDimension。我还具有在单击它时更改单元格大小的功能。
因此,在我的任务中,这工作正常:
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return presenter.cellHeights[indexPath.row] ?? 0
}
但我认为你可以立即设置高度:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return presenter.cellHeights[indexPath.row] ?? 0
}