删除项目后为 CollectionViewCell 设置动画
Posted
技术标签:
【中文标题】删除项目后为 CollectionViewCell 设置动画【英文标题】:Animate CollectionViewCell after deleting item 【发布时间】:2020-03-31 13:22:18 【问题描述】:对于我的CollectionView
,我在willDisplay
中有这个animation
:
func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath)
// Add animations here
let animation = AnimationFactory.makeMoveUpWithFade(rowHeight: cell.frame.height, duration: 0.5, delayFactor: 0.1)
let animator = Animator(animation: animation)
animator.animate(cell: cell, at: indexPath, in: collectionView)
This 是动画的工作方式(我为CollectionView
实现了它)如果您需要它以获取更多信息。
问题:
在我的项目中,用户可以create
和delete
和item
。
现在collectionView
在deleting
之后没有动画,即使我正在调用reloadData
:
extension MainViewController: DismissWishlistDelegate
func dismissWishlistVC(dataArray: [Wishlist], dropDownArray: [DropDownOption])
self.dataSourceArray = dataArray
self.dropOptions = dropDownArray
self.makeWishView.dropDownButton.dropView.tableView.reloadData()
// reload the collection view
theCollectionView.reloadData()
theCollectionView.performBatchUpdates(nil, completion: nil)
这是我在另一个ViewController
中调用delegate
的地方:
func deleteTapped()
let alertcontroller = UIAlertController(title: "Wishlist löschen", message: "Sicher, dass du diese Wishlist löschen möchtest?", preferredStyle: .alert)
let deleteAction = UIAlertAction(title: "Löschen", style: .default) (alert) in
DataHandler.deleteWishlist(self.wishList.index)
self.dataSourceArray.remove(at: self.currentWishListIDX)
self.dropOptions.remove(at: self.currentWishListIDX)
// change heroID so wishlist image doesnt animate
self.wishlistImage.heroID = "delete"
self.dismiss(animated: true, completion: nil)
// update datasource array in MainVC
self.dismissWishlistDelegate?.dismissWishlistVC(dataArray: self.dataSourceArray, dropDownArray: self.dropOptions)
let cancelAction = UIAlertAction(title: "Abbrechen", style: .default) (alert) in
print("abbrechen")
alertcontroller.addAction(cancelAction)
alertcontroller.addAction(deleteAction)
self.present(alertcontroller, animated: true)
当creating
动画效果很好。这就是我的createDelegateFunction
的样子:
func createListTappedDelegate(listImage: UIImage, listImageIndex: Int, listName: String)
// append created list to data source array
var textColor = UIColor.white
if Constants.Wishlist.darkTextColorIndexes.contains(listImageIndex)
textColor = UIColor.darkGray
let newIndex = self.dataSourceArray.last!.index + 1
self.dataSourceArray.append(Wishlist(name: listName, image: listImage, wishData: [Wish](), color: Constants.Wishlist.customColors[listImageIndex], textColor: textColor, index: newIndex))
// append created list to drop down options
self.dropOptions.append(DropDownOption(name: listName, image: listImage))
// reload the collection view
theCollectionView.reloadData()
theCollectionView.performBatchUpdates(nil, completion:
(result) in
// scroll to make newly added row visible (if needed)
let i = self.theCollectionView.numberOfItems(inSection: 0) - 1
let idx = IndexPath(item: i, section: 0)
self.theCollectionView.scrollToItem(at: idx, at: .bottom, animated: true)
)
【问题讨论】:
【参考方案1】:使用finalLayoutAttributesForDisappearingItem(at:)
和initialLayoutAttributesForAppearingItem(at:) 正确完成IUCollectionView
元素插入和删除的动画
Apple 在finalLayoutAttributesForDisappearingItem(at:)
上的文档摘录
此方法在prepare(forCollectionViewUpdates:) 方法之后和finalizeCollectionViewUpdates() 方法之前调用,用于任何即将被删除的项目。您的实现应该返回描述项目最终位置和状态的布局信息。集合视图使用此信息作为任何动画的终点。 (动画的起点是项目的当前位置。)如果返回 nil,则布局对象对动画的起点和终点使用相同的属性。
【讨论】:
@Chris,Objc.io 博客上提供了很好的解释(文章示例在 Objective C 中,但此后 api 没有太大变化):objc.io/issues/12-animations/collectionview-animations @Chris,CollectionView 在很大程度上取决于布局。在不更改布局的情况下执行影响布局的动画可能容易出错,并可能导致视觉错误。这是我的观点。如果你愿意,你可以使用你的方法,ofc。 感谢您的回答和解释!但现在我想我会坚持我的方式,从来没有任何问题。您对如何解决实际问题有想法吗? 我想要的是一些我可以从reloads
collectionView
和animation
的任何地方调用的函数【参考方案2】:
我通过删除performBatchUpdates
解决了这个问题...我不知道它为什么现在起作用以及performBatchUpdates
到底做了什么,但它起作用了,所以如果有人想向我解释它,请随意:D
最终的函数如下所示:
func dismissWishlistVC(dataArray: [Wishlist], dropDownArray: [DropDownOption], shouldDeleteWithAnimation: Bool, indexToDelete: Int)
if shouldDeleteWithAnimation
self.shouldAnimateCells = true
self.dataSourceArray.remove(at: self.currentWishListIDX)
self.dropOptions.remove(at: self.currentWishListIDX)
// reload the collection view
theCollectionView.reloadData()
else
self.shouldAnimateCells = false
self.dataSourceArray = dataArray
self.dropOptions = dropDownArray
// reload the collection view
theCollectionView.reloadData()
theCollectionView.performBatchUpdates(nil, completion: nil)
self.makeWishView.dropDownButton.dropView.tableView.reloadData()
【讨论】:
以上是关于删除项目后为 CollectionViewCell 设置动画的主要内容,如果未能解决你的问题,请参考以下文章
在点击手势上重置 CollectionviewCell 位置