UITableView 没有正确地为在屏幕外重新排序的单元格设置动画

Posted

技术标签:

【中文标题】UITableView 没有正确地为在屏幕外重新排序的单元格设置动画【英文标题】:UITableView not correctly animating cells that are re-ordered off screen 【发布时间】:2018-05-19 11:39:42 【问题描述】:

我正在为我的数据源使用 NSFetchedResultsController。

当我对单元格重新排序并且它向上或向下移动到屏幕上或稍微离开屏幕的位置时,单元格会通过动画移动到新位置。

但是,当该行移动到远离屏幕的新位置时,它只是在没有任何动画的情况下移动。

理想情况下,在这些情况下,我希望行向下或向上动画,直到它离开屏幕。有没有办法在不实现自定义方法的情况下实现这一点?

我在这里使用的案例是以下委托调用中的 .move:

func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) 
    switch type 
    case .insert:
        tableView.insertRows(at: [newIndexPath!], with: UITableViewRowAnimation.none)
    case .delete:
        tableView.deleteRows(at: [indexPath!], with: UITableViewRowAnimation.none)
    case .update:
        tableView.reloadRows(at: [indexPath!], with: UITableViewRowAnimation.none)
    case .move:
        tableView.moveRow(at: indexPath!, to: newIndexPath!)
    


【问题讨论】:

你试过UITableViewRowAnimation.fade或类似的东西。 是的,这根本没有区别 【参考方案1】:

从docs 开始,UIKit 将为所有单元格的移动操作设置动画,但是它发生得如此之快以至于它不是很直观。

所以,你实际上可以通过两个move(at:,to:) 调用performBatchUpdates 来获得想要的效果,如下所示:

guard indexPath != newIndexPath, let paths = tableView.indexPathsForVisibleRows else  return 
if paths.contains(newIndexPath!) 
    tableView.moveRow(at: indexPath!, to: newIndexPath!)
 else 
    tableView.performBatchUpdates(
        let index = indexPath < newIndexPath ? (paths.count - 1) : 2
        tableView.moveRow(at:indexPath!, to: paths[index])
        tableView.moveRow(at: paths[index], to: newIndexPath!)
    )

注意,要实现向上滚动动画,你必须将paths索引设置为2作为向上移动的中点。

【讨论】:

非常好的解决方案,但不幸的是它只适用于向下移动的行,不适用于向上移动的行。使用路径。首先!因为行向上移动的中点会导致一些奇怪的动画。此外,有时甚至向下移动的行也会停在中间位置,并且不会一直向下移动。 @alionthego 查看我更新的向上滚动答案。对于另一个问题,可以调整此代码以使用多个中间移动操作进行动画处理。如果两行相距很远,就会出现问题。 :)

以上是关于UITableView 没有正确地为在屏幕外重新排序的单元格设置动画的主要内容,如果未能解决你的问题,请参考以下文章

UITableView 没有正确重新加载

UITableView 没有正确对齐

UITableView 两次重新加载数据,但没有正确显示数据

即使在屏幕外,iOS UITableView 单元格也会加载

iOS6 和 UITableView 中的屏幕外 UITextView

重新加载 UIViewController 而不返回 UITableView