I'm trying out the new compositional layout APIs introduced with iOS13, they're pretty great - but I'm having an issue with one thing in particular and there's very little official documentation about it.
I'm looking to perform an animation on a NSCollectionLayoutVisibleItem
object using visibleItemsInvalidationHandler
. I've tried two different approaches so far:
UIView
property animatorslayoutSection.visibleItemsInvalidationHandler = { (visibleItems, offset, env) in
let normalizedOffsetX = offset.x + centeredPadding
let centerPoint = CGPoint(x: normalizedOffsetX + collectionView.bounds.width / 2, y: 20)
visibleItems.forEach({ item in
UIView.animate(withDuration: 0.3) {
item.transform = item.frame.contains(centerPoint) ? .identity : CGAffineTransform(scaleX: 0.9, y: 0.9)
}
})
}
CATransaction
animatorslayoutSection.visibleItemsInvalidationHandler = { (visibleItems, offset, env) in
let normalizedOffsetX = offset.x + centeredPadding
let centerPoint = CGPoint(x: normalizedOffsetX + collectionView.bounds.width / 2, y: 20)
visibleItems.forEach({ item in
CATransaction.begin()
CATransaction.setAnimationDuration(0.3)
CATransaction.setCompletionBlock {
item.transform = item.frame.contains(centerPoint) ? .identity : CGAffineTransform(scaleX: 0.9, y: 0.9)
}
CATransaction.commit()
})
}
Neither of these approaches work - however, although not animated, I do see the transform
changes reflected on the UI.
I've just discovered how to do this and hopefully this will help someone else. The key seems to be to use the indexPath
property on the NSCollectionLayoutVisibleItem
to then retrieve the UITableViewCell
from the UICollectionView
and perform any animations on it instead.
Here's how I ended up solving my problem:
layoutSection.visibleItemsInvalidationHandler = { (visibleItems, offset, env) in
let normalizedOffsetX = offset.x + centeredPadding
let centerPoint = CGPoint(x: normalizedOffsetX + collectionView.bounds.width / 2, y: 20)
visibleItems.forEach({ item in
guard let cell = collectionView.cellForItem(at: item.indexPath) else { return }
UIView.animate(withDuration: 0.3) {
cell.transform = item.frame.contains(centerPoint) ? .identity : CGAffineTransform(scaleX: 0.9, y: 0.9)
}
})
}