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
        })
    }