不断更新单元格大小时滚动到顶部的问题

问题描述 投票:1回答:3

我有一个带自动调整大小的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()
}

这工作得相当好,但是当用户点击滚动到列表顶部时会出现问题。动画有点笨拙,往往没有时间到顶部。有没有更好的方法来处理这个?

ios swift uitableview
3个回答
1
投票

如果在滚动表时设置了标志,则可以在计时器功能中检测到该标志,并在设置时不进行更新。 UITableViewUIScrollView的后代,因此您可以使用一些滚动视图代表来执行此操作。如果您覆盖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
}

我已经在函数中添加了一些日志记录,以便您可以看到正在发生的事情。当然,你可以删除这些。


0
投票

当点击滚动到顶部时,计时器无效,然后一旦到达顶部再次启动计时器。

编辑:这样,它不会更新可能在不更新表格视图的“顶部”的情况下移动内容更高的内容。


0
投票

我遇到了类似的问题。我借助每个单元格的手动高度计算解决了这个问题。

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
}
© www.soinside.com 2019 - 2024. All rights reserved.