How to animate a UICollectionView cell selection
The animated
in UICollectionView
's selectItem(at:animated:scrollPosition:)
determines whether the item to-be-selected, if not in view or at required position already, should be scrolled to in an animated fashion or not.
If it's in view then this animated
property doesn't really do anything, afaik.
Same for the animated
in deselectItem(at:animated:)
. It doesn't do anything and is simply there.
The only thing I see affecting the layout engine is if the collectionView
scrolls and you have animations in the didSelectItemAt
then it will render these animations ineffective. You would have to delay the animations occurring in the cell (see last example in this answer)
As you already know but for others, if you want to animate the cell selection event then you will have to do it yourself in the collectionView(_:didSelectItemAt:)
delegate.
Example:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let cell = collectionView.cellForItem(at: indexPath)
//Briefly fade the cell on selection
UIView.animate(withDuration: 0.5,
animations: {
//Fade-out
cell?.alpha = 0.5
}) { (completed) in
UIView.animate(withDuration: 0.5,
animations: {
//Fade-out
cell?.alpha = 1
})
}
}
The above is fine if the user taps on a cell but if you programmatically call selectItem(at:animated:scrollPosition:)
, it won't trigger the above collectionView(_:didSelectItemAt:)
delegate and you would need to explicitly call it to run your selection animation.
Example (Add-on to previous):
func doSelect(for aCollectionView: UICollectionView,
at indexPath: IndexPath) {
aCollectionView.selectItem(at: indexPath,
animated: true,
scrollPosition: .centeredVertically)
//DispatchQueue after sometime because scroll animation renders
//the animation block in `collectionView(_:didSelectItemAt:)` ineffective
DispatchQueue.main.asyncAfter(deadline: .now() + 0.27) { [weak self] in
self?.collectionView(aCollectionView,
didSelectItemAt: indexPath)
}
}
I would suggest overriding isHighlighted
property of UICollectionViewCell
with animation. That way if a user taps on a cell and stops to think what to do next, the animation state will be preserved.
override var isHighlighted: Bool {
didSet {
toggleIsHighlighted()
}
}
func toggleIsHighlighted() {
UIView.animate(withDuration: 0.1, delay: 0, options: [.curveEaseOut], animations: {
self.alpha = self.isHighlighted ? 0.9 : 1.0
self.transform = self.isHighlighted ?
CGAffineTransform.identity.scaledBy(x: 0.97, y: 0.97) :
CGAffineTransform.identity
})
}