What does the animated
argument of these methods of UICollectionView
do:
selectItem(at indexPath: IndexPath?, animated: Bool, scrollPosition: UICollectionViewScrollPosition)`
deselectItem(at indexPath: IndexPath, animated: Bool)
I know I can use the UICollectionViewLayout
object to animate changes. I also know that I can use didSelect
and didDeselect
methods of the UICollectionViewDelegate
to get the selected cell and apply animations. But I can't find any information about how the above animated
argument affects animations. Does it affect the layout animations in any way? My goal is to create a UICollectionView
subclass and allow the consumer to customize whether animations apply when the above two methods are called internally. But I don't know what animations those methods control.
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
})
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With