使用自定义 UICollectionViewLayout 无缝移动隐藏的 UICollectionViewCell

Move hidden UICollectionViewCell seamlessly with a custom UICollectionViewLayout

我实现了一种自定义机制,使用 UICollectionView 中的拖放执行重新排序,使用 UILongPressGestureRecognizer

我有一个很简单的UICollectionView with a custom UICollectionViewLayout
我的布局 class 不是 UICollectionViewFlowLayout 的子 class。

这是它的样子:

当我开始抬起一个单元格开始拖动时,我更新了自定义布局对象中的 dropProposalIndexPath 属性,以便它知道需要隐藏哪个单元格。

My custom UICollectionViewLayout subclass returns a UICollectionViewLayoutAttributes with the alpha 属性 set to 0 for the cell which the corresponding to dropProposalIndexPath 像这样:

if self.dropProposalIndexPath == indexPath {
    itemLayoutAttributes.alpha = 0
}

它使提升的单元格隐藏,从而在 UICollectionView.

中创建一个 "hole"

当用户移动手指时,我更新自定义 UICollectionViewLayout subclass 的 dropProposalIndexPath 属性 并使其布局无效,然后移动动作的单元格作为新 indexPath 的一个洞:

// Inform layout of the indexPath of the dropProposal
self.reorderableLayout?.dropProposalIndexPath = dropProposalIndexPath
// Move the cell 
collectionView.moveItem(at: draggingIndexPath, to: dropProposalIndexPath)

外观如下:

很糟糕吧?

我使用 UICollectionViewFlowLayout 的子 class 在演示项目中实现了完全相同的逻辑,并且过渡是无缝的:

我想我做错了什么或忘记在我的 UICollectionViewLayout 子class.

中做某事

如果需要,我可以 post 更多代码。


请注意,使用内置的拖放机制(在 iOS 11 中引入)执行重新排序不是一种选择,出于各种原因我想使用我的自定义实现。

如果有人遇到同样的问题,解决方案是在您的 UICollectionViewLayout 子类中实现以下方法:

func initialLayoutAttributesForAppearingItem(at: IndexPath) -> UICollectionViewLayoutAttributes?

你然后 return 一个 UICollectionViewLayoutAttributesalpha 属性 在 initialLayoutAttributesForAppearingItem 函数中设置为 0 如果 itemIndexPath 参数与您拖动单元格的 indexPath 相匹配。