在 iOS 11 中,Apple 向 TableViews 引入了原生拖放功能,它为常见的拖放交互提供了特定的动画。假设您返回了正确的 UIDropProposal 它会很容易地在表格视图中为重新排序的放置设置动画
func tableView(_ tableView: UITableView, performDropWith coordinator: UITableViewDropCoordinator) {
// usual code to handle drop, get dragItem, etc
// ....
// update the dataModel to reflect the change
self?.model.updateDataSourceForDrag(from: sourceIndexPath, to: destinationIndexPath)
// perform the drop animation with the drop coordinator
coordinator.drop(dragItem, toRowAt: destinationIndexPath)
}
这将很好地动画将放置的项目插入 tableView 到它悬停的间隙中。
快进到 iOS 13+ 和 diffable 数据源的使用,我在 Apple 文档中找不到使用带有快照的 dropCoordinator 的参考,并且没有更新指南、教程或 WWDC 视频来展示如何组合两组 API。
拖放控制器将在拖动操作期间正确“管理” tableView 并移动单元格以显示拖动单元格将下降的间隙,但它不会使用coordinator.drop(dragItem, toRowAt: destinationIndexPath)
.
我目前的解决方法是手动更新然后应用快照:
DispatchQueue.main.async {
var snapshot = self?.dataSource.snapshot()
if destinationIndexPath.row > sourceIndexPath.row {
snapshot?.moveItem((self?.dataSource.itemIdentifier(for: sourceIndexPath))!, afterItem: (self?.dataSource.itemIdentifier(for: destinationIndexPath))!)
} else {
snapshot?.moveItem((self?.dataSource.itemIdentifier(for: sourceIndexPath))!, beforeItem: (self?.dataSource.itemIdentifier(for: destinationIndexPath))!)
}
self?.dataSource.apply(snapshot!, animatingDifferences: false)
}
这在一定程度上有效,但它没有与放置控制器动画集成。因此,当我拖动时,我可以获得在 tableView 中提供放置间隙的动画,但是一旦我放下它,单元格就会从其原始 indexPath 移动而不是从动画放置的项目移动(正如我所期望的这种解决方法),这是都相当笨重。
dropCoordinator 可以使 tableView 为拖动设置动画,这表明它也应该能够为 drop 设置动画,但我找不到实现这一点的方法。
任何这方面的经验都将不胜感激(在我放弃并将代码恢复为旧的 UITableViewDataSource 方法之前)。