问题描述
新年快乐! ?
我正在尝试使用动画插入和删除部分和元素来制作自定义布局。同时,重要的是所有元素都是自定大小。
一切正常,除了一件事:获取其大小的请求,标题接收最后一个,尽管我需要它首先接收它。因此,我的单元格在动画开始时处于错误的位置。
我会尝试更详细地解释...
- 这一切都始于一个方法调用
prepare(forAnimatedBoundsChange:)
,在那里我更新了我的内部属性模型。 -
initialLayoutAttributesForAppearingItem(at:)
方法被调用,其中对于我插入的部分中包含的每个单元格,在返回属性之前,我复制属性以便能够更改它们,因为我得到了它们的最终大小稍后。
override func initialLayoutAttributesForAppearingItem(at itemIndexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
if itemIndexPathsToInsert.contains(itemIndexPath) || sectionIndicesToInsert.contains(itemIndexPath.section) {
let item = sections.item(at: itemIndexPath).copy() as! InsetGroupedLayoutAttributes
item.alpha = 0.0
itemsForPendingAnimations[itemIndexPath] = item
return item
} else {
return super.initialLayoutAttributesForAppearingItem(at: itemIndexPath)
}
}
3 然后调用 invalidationContext(forPreferredLayoutAttributes:withOriginalAttributes:)
方法获得最终尺寸
override func invalidationContext(forPreferredLayoutAttributes preferredAttributes: UICollectionViewLayoutAttributes,withOriginalAttributes originalAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutInvalidationContext {
let invalidationContext = super.invalidationContext(forPreferredLayoutAttributes: preferredAttributes,withOriginalAttributes: originalAttributes)
let indexPath = preferredAttributes.indexPath
let height = preferredAttributes.frame.height.rounded(.up)
switch preferredAttributes.representedElementCategory {
case .cell:
print("cell",#function)
sections.updateItem(at: indexPath,withNewHeight: height)
itemsForPendingAnimations[indexPath]?.frame = sections.item(at: indexPath).frame
// itemsForPendingAnimations[indexPath]?.transform = .init(scaleX: 0.8,y: 0.8)
invalidationContext.invalidateItems(at: [indexPath])
case .supplementaryView:
print("supplementary",#function)
sections.updateHeader(forSectionIndex: indexPath.section,withNewHeight: height)
supplementaryElementsForPendingAnimations[indexPath]?.frame = sections.supplementaryElement(at: indexPath).frame
itemsForPendingAnimations.forEach { $0.value.frame = sections.item(at: $0.key).frame }
invalidationContext.invalidateSupplementaryElements(ofKind: InsetGroupedHeaderCollectionReusableView.kind,at: [indexPath])
default:
assertionFailure()
}
return invalidationContext
}
- 最后调用了
layoutAttributesForItem(at:)
方法,之后就不能再改变我复制的属性了,动画会从调用这个方法后属性保持的状态开始。
此外,将对插入部分的所有单元格重复从 2 到 4 的调用并且仅在此之后为补充元素调用相应的方法。 initialLayoutAttributesForAppearingSupplementaryElement(ofKind:at:)
、invalidationContext(forPreferredLayoutAttributes:withOriginalAttributes:)
和 layoutAttributesForSupplementaryView(ofKind:at:)
。在这里,我的标题获得了最终大小,此标题之后的所有单元格也应调整大小,但我无法再更改动画初始状态的属性。
记录调用以插入其中一个部分:
prepare(forCollectionViewUpdates:)
initialLayoutAttributesForAppearingItem(at:) [1,0]
cell invalidationContext(forPreferredLayoutAttributes:withOriginalAttributes:)
layoutAttributesForItem(at:) [1,0]
initialLayoutAttributesForAppearingItem(at:) [1,1]
cell invalidationContext(forPreferredLayoutAttributes:withOriginalAttributes:)
layoutAttributesForItem(at:) [1,1]
initialLayoutAttributesForAppearingItem(at:) [1,2]
cell invalidationContext(forPreferredLayoutAttributes:withOriginalAttributes:)
layoutAttributesForItem(at:) [1,2]
initialLayoutAttributesForAppearingItem(at:) [1,3]
cell invalidationContext(forPreferredLayoutAttributes:withOriginalAttributes:)
layoutAttributesForItem(at:) [1,3]
initialLayoutAttributesForAppearingItem(at:) [1,4]
cell invalidationContext(forPreferredLayoutAttributes:withOriginalAttributes:)
layoutAttributesForItem(at:) [1,4]
initialLayoutAttributesForAppearingSupplementaryElement(ofKind:at:) [1,0] <--- Should be called first
supplementary invalidationContext(forPreferredLayoutAttributes:withOriginalAttributes:) <--- Should be called first
layoutAttributesForSupplementaryView(ofKind:at:) [1,0] <--- Should be called first
finalizeCollectionViewUpdates()
因此,插入发生时单元格的轻微移动,因为在调整标题大小后我无法再更改它们的位置:
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)