UITableView 单元格折叠动画看起来很糟糕

Ale*_*Maj 5 uitableview ios swift ios11

我在使单元折叠动画看起来始终平滑时遇到问题。

我的形象抵得上一千个字。这是同一表视图的两个 GIF:

伟大的 糟糕的

折叠对于单元格“6”非常有效,但对于“5”则不然。看起来整个 UITableView 内容在执行折叠动画之前都会跳起来。

没有使用UITableViewAutomaticDimensionUITableView's rowHeight。相反,我通过方法提供行高,并使用表视图的 / 扩展/tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath)折叠单元格。正如您所看到的,我还使用滚动到展开的行(但仅在展开时,所以这可能并不重要)。beginUpdatesendUpdatestableView.scrollToRow(at: indexPath, at: .none, animated: true)

UITableViewController 的子类嵌入在具有大标题和搜索栏的 UINavigationController 中(此处不可见,因为内容向下滚动)。UINavigationController 嵌入在 UITabBarController 中。

这是相关的展开/折叠部分。当传递 nilindexPath参数时,已经展开的单元格将折叠。

func expandRow(at indexPath: IndexPath?) {
    selectedIndexPath = indexPath
    tableView.beginUpdates()
    tableView.endUpdates()

    if let ip = indexPath {
        tableView.scrollToRow(at: ip, at: .none, animated: true)
    }
}
Run Code Online (Sandbox Code Playgroud)

tableView(_:heightForRowAt:)此方法计算行高并由和调用tableView(_:estimatedHeightForRowAt:)

private func heightForRow(at indexPath: IndexPath) -> CGFloat {
    var height: CGFloat
    if selectedIndexPath == indexPath {
        // Add some height variety
        height = 300 + CGFloat((indexPath.row % 4) * 20)
    } else {
        height = 70
    }
    return height
}
Run Code Online (Sandbox Code Playgroud)

这是 GitHub 存储库:https://github.com/AleksanderMaj/CellCollapse

知道如何改进吗?

此问题与尺寸敏感(在具有不同屏幕尺寸的设备上执行相同步骤后,可能无法重现此问题)。这是在装有 iOS 11.3 的 iPhone 7 模拟器上录制的。


编辑 1:保留自动滚动到展开的单元格非常重要。

HAK*_*HAK 6

我能够通过对您的扩展方法进行微小的更改来使其顺利:

func expandRow(at indexPath: IndexPath?) {
    selectedIndexPath = indexPath
    tableView.beginUpdates()
    tableView.endUpdates()

    if let ip = indexPath {
        tableView.scrollToRow(at: ip, at: .middle, animated: true)
    }
}
Run Code Online (Sandbox Code Playgroud)

前 后


Tar*_*nko 1

您正在滚动到展开的行,这使得 UITableView 跳跃了一点。

所以这里有一个重构的expandRow(at:)方法:

func expandRow(at indexPath: IndexPath?) {
    self.contentOffset = self.tableView.contentOffset
    selectedIndexPath = indexPath
    tableView.beginUpdates()
    tableView.endUpdates()

    if let contentOffset = self.contentOffset {
        tableView.contentOffset = contentOffset
    }
}
Run Code Online (Sandbox Code Playgroud)

var contentOffset: CGPoint?您还需要向控制器添加属性。

更新 我错了,你不需要顺便说selectedIndexPath = indexPath一句beginUpdates()endUpdates()方法。更新的代码示例